grim/govcs
Clone
Summary
Browse
Changes
Graph
Add subversion support
draft
2017-12-27, Gary Kramlich
8f7139d219b9
Parents
e3e0b8f91448
Children
063c05e63cab
Add subversion support
2 files changed, 223 insertions(+), 0 deletions(-)
+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())
+}