grim/govcs

Add subversion support
draft
2017-12-27, Gary Kramlich
8f7139d219b9
Parents e3e0b8f91448
Children 063c05e63cab
Add subversion support
  • +120 -0
    svn/svn.go
  • +103 -0
    svn/svn_test.go
  • --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/svn/svn.go Wed Dec 27 23:17:42 2017 -0600
    @@ -0,0 +1,120 @@
    +// govcs
    +// Copyright 2017 Gary Kramlich <grim@reaperworld.com>
    +//
    +// This program is free software: you can redistribute it and/or modify
    +// it under the terms of the GNU General Public License as published by
    +// the Free Software Foundation, either version 3 of the License, or
    +// (at your option) any later version.
    +//
    +// This program is distributed in the hope that it will be useful,
    +// but WITHOUT ANY WARRANTY; without even the implied warranty of
    +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    +// GNU General Public License for more details.
    +//
    +// You should have received a copy of the GNU General Public License
    +// along with this program. If not, see <http://www.gnu.org/licenses/>.
    +
    +// Package git interacts with Git repositories.
    +package svn
    +
    +import (
    + "encoding/xml"
    + "fmt"
    + "strings"
    +
    + "bitbucket.org/rw_grim/govcs/exec"
    + "bitbucket.org/rw_grim/govcs/vcs"
    +)
    +
    +type svnCommit struct {
    + Revision string `xml:"revision,attr"`
    +}
    +
    +type rawSubversion struct {
    + Remote string `xml:"entry>repository>root"`
    + Root string `xml:"entry>wc-info>wcroot-abspath"`
    + Commit svnCommit `xml:"entry>commit"`
    + Branch string `xml:"entry>relative-url"`
    +}
    +
    +// SVN is an instance of vcs.VCS that will operate on a Subversion repository.
    +type Subversion struct {
    + wd string
    + raw rawSubversion
    +}
    +
    +// Detect will return a vcs.VCS instance if the given working directory is a
    +// Git repository.
    +func Detect(wd string) vcs.VCS {
    + s := &Subversion{
    + wd: wd,
    + }
    +
    + err := s.info()
    + if err != nil {
    + fmt.Printf("%#v\n", err)
    + return nil
    + }
    +
    + return s
    +}
    +
    +// Remote will return the url for repository. The given remote name is ignored
    +// as subversion does not support multiple remotes.
    +func (s *Subversion) Remote(name string) string {
    + return s.raw.Remote
    +}
    +
    +// Root will return the root of the repository.
    +func (s *Subversion) Root() string {
    + return s.raw.Root
    +}
    +
    +// Commit will return the commit id of the repository.
    +func (s *Subversion) Commit() string {
    + return s.raw.Commit.Revision
    +}
    +
    +// ShortCommit returns the short commit id of the repository.
    +func (s *Subversion) ShortCommit() string {
    + return s.raw.Commit.Revision
    +}
    +
    +// Branch returns the name of the checked out branch.
    +func (s *Subversion) Branch() string {
    + return s.raw.Branch
    +}
    +
    +// Config will look up the given key and return a string slice of the values.
    +func (s *Subversion) Config(key string) []string {
    + return []string{}
    +}
    +
    +// run `svn info $WD` and store the results in s.raw
    +func (s *Subversion) info() error {
    + cmd := exec.Command("svn", "info", "--config-dir", "/dev/null", s.wd)
    + output, err := cmd.Output()
    + if err != nil {
    + return err
    + }
    +
    + var raw rawSubversion
    + err = xml.Unmarshal(output, &raw)
    + fmt.Printf("rawSubversion: %#v\n", raw)
    + if err != nil {
    + return err
    + }
    +
    + s.raw = raw
    +
    + // parse the branch now
    + if s.raw.Branch == "^/trunk" {
    + s.raw.Branch = "trunk"
    + } else if strings.HasPrefix(s.raw.Branch, "^/branches/") {
    + s.raw.Branch = s.raw.Branch[11:]
    + } else if strings.HasPrefix(s.raw.Branch, "^/tags/") {
    + s.raw.Branch = s.raw.Branch[7:]
    + }
    +
    + return nil
    +}
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/svn/svn_test.go Wed Dec 27 23:17:42 2017 -0600
    @@ -0,0 +1,103 @@
    +// govcs
    +// Copyright 2017 Gary Kramlich <grim@reaperworld.com>
    +//
    +// This program is free software: you can redistribute it and/or modify
    +// it under the terms of the GNU General Public License as published by
    +// the Free Software Foundation, either version 3 of the License, or
    +// (at your option) any later version.
    +//
    +// This program is distributed in the hope that it will be useful,
    +// but WITHOUT ANY WARRANTY; without even the implied warranty of
    +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    +// GNU General Public License for more details.
    +//
    +// You should have received a copy of the GNU General Public License
    +// along with this program. If not, see <http://www.gnu.org/licenses/>.
    +
    +package svn
    +
    +import (
    + "errors"
    + "testing"
    +
    + "github.com/aphistic/sweet"
    + junit "github.com/aphistic/sweet-junit"
    + . "github.com/onsi/gomega"
    +
    + "bitbucket.org/rw_grim/govcs/exec"
    +)
    +
    +type svnSuite struct{}
    +
    +var (
    + data = `<?xml version="1.0" encoding="UTF-8"?>
    +<info>
    +<entry
    + kind="dir"
    + path="."
    + revision="1">
    +<url>file:///vcs/svn-repo/trunk</url>
    +<relative-url>^/trunk</relative-url>
    +<repository>
    +<root>file:///vcs/svn-repo</root>
    +<uuid>6469bf1c-c3bf-4669-9443-0d5bf139ee55</uuid>
    +</repository>
    +<wc-info>
    +<wcroot-abspath>/vcs/foo/bar/baz</wcroot-abspath>
    +<schedule>normal</schedule>
    +<depth>infinity</depth>
    +</wc-info>
    +<commit
    + revision="1">
    +<author>grim</author>
    +<date>2017-12-28T03:24:37.037145Z</date>
    +</commit>
    +</entry>
    +</info>`
    +)
    +
    +func TestMain(m *testing.M) {
    + RegisterFailHandler(sweet.GomegaFail)
    +
    + sweet.Run(m, func(s *sweet.S) {
    + s.RegisterPlugin(junit.NewPlugin())
    +
    + s.AddSuite(&svnSuite{})
    + })
    +}
    +
    +func (s *svnSuite) setup(cmd exec.Cmd) exec.ExecBackend {
    + backend := exec.Backend()
    +
    + exec.SetBackend(func(name string, args ...string) exec.Cmd {
    + return cmd
    + })
    +
    + return backend
    +}
    +
    +func (s *svnSuite) TestDetectFound(t sweet.T) {
    + backend := s.setup(exec.NewMockCommand(data, nil))
    + defer exec.SetBackend(backend)
    +
    + vcs := Detect("working-directory")
    + Expect(vcs).ToNot(BeNil())
    +
    + svn, ok := vcs.(*Subversion)
    + Expect(ok).To(BeTrue())
    + Expect(svn.wd).To(Equal("working-directory"))
    +
    + Expect(svn.Root()).To(Equal("/vcs/foo/bar/baz"))
    + Expect(svn.Remote("")).To(Equal("file:///vcs/svn-repo"))
    + Expect(svn.Commit()).To(Equal("1"))
    + Expect(svn.ShortCommit()).To(Equal("1"))
    + Expect(svn.Branch()).To(Equal("trunk"))
    +}
    +
    +func (s *svnSuite) TestDetectNotFound(t sweet.T) {
    + backend := s.setup(exec.NewMockCommand("", errors.New("not found")))
    + defer exec.SetBackend(backend)
    +
    + vcs := Detect("")
    + Expect(vcs).To(BeNil())
    +}