[ARVADOS] updated: b93018f033f37a7a7b719fd7dc6d5b3ad4a0f797

git at public.curoverse.com git at public.curoverse.com
Mon Mar 16 17:16:05 EDT 2015


Summary of changes:
 services/api/app/models/repository.rb       |  10 +-
 services/api/test/fixtures/repositories.yml |  14 +++
 services/api/test/unit/repository_test.rb   |  12 ++-
 services/arv-git-httpd/auth_handler.go      |   4 -
 services/arv-git-httpd/doc.go               |  22 ++++
 services/arv-git-httpd/main.go              |   8 ++
 services/arv-git-httpd/server.go            |  10 +-
 services/arv-git-httpd/server_test.go       | 152 ++++++++++++++++++++++++++++
 8 files changed, 221 insertions(+), 11 deletions(-)
 create mode 100644 services/arv-git-httpd/server_test.go

       via  b93018f033f37a7a7b719fd7dc6d5b3ad4a0f797 (commit)
       via  c106899198b67d1071ccf164ce743b651981f8cd (commit)
       via  eb68ddf0ab91faf6ce1dbab4b8db81b56ffeccaf (commit)
      from  16421a1aa8d420728b51d7cbb1b006a5613f8697 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit b93018f033f37a7a7b719fd7dc6d5b3ad4a0f797
Author: Tom Clegg <tom at curoverse.com>
Date:   Mon Mar 16 17:17:07 2015 -0400

    5416: Allow users with repo write permission to update modified_at.

diff --git a/services/api/app/models/repository.rb b/services/api/app/models/repository.rb
index f159b48..0189ee7 100644
--- a/services/api/app/models/repository.rb
+++ b/services/api/app/models/repository.rb
@@ -22,7 +22,15 @@ class Repository < ArvadosModel
   def permission_to_create
     current_user and current_user.is_admin
   end
+
   def permission_to_update
-    current_user and current_user.is_admin
+    return false if not current_user
+    return true if current_user.is_admin
+    # For normal objects, this is a way to check whether you have
+    # write permission. Repositories should be brought closer to the
+    # normal permission model during #4253. Meanwhile, we'll
+    # special-case this so arv-git-httpd can detect write permission:
+    return super if changed_attributes.keys - ['modified_at', 'updated_at'] == []
+    false
   end
 end
diff --git a/services/api/test/fixtures/repositories.yml b/services/api/test/fixtures/repositories.yml
index a0e3b1f..b80414d 100644
--- a/services/api/test/fixtures/repositories.yml
+++ b/services/api/test/fixtures/repositories.yml
@@ -2,33 +2,47 @@ crunch_dispatch_test:
   uuid: zzzzz-s0uqq-382brsig8rp3665
   owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
   name: crunch_dispatch_test
+  created_at: 2015-01-01T00:00:00.123456Z
+  modified_at: 2015-01-01T00:00:00.123456Z
 
 arvados:
   uuid: zzzzz-s0uqq-arvadosrepo0123
   owner_uuid: zzzzz-tpzed-000000000000000 # root
   name: arvados
+  created_at: 2015-01-01T00:00:00.123456Z
+  modified_at: 2015-01-01T00:00:00.123456Z
 
 foo:
   uuid: zzzzz-s0uqq-382brsig8rp3666
   owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
   name: foo
+  created_at: 2015-01-01T00:00:00.123456Z
+  modified_at: 2015-01-01T00:00:00.123456Z
 
 repository2:
   uuid: zzzzz-s0uqq-382brsig8rp3667
   owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
   name: foo2
+  created_at: 2015-01-01T00:00:00.123456Z
+  modified_at: 2015-01-01T00:00:00.123456Z
 
 repository3:
   uuid: zzzzz-s0uqq-38orljkqpyo1j61
   owner_uuid: zzzzz-tpzed-d9tiejq69daie8f # admin user
   name: foo3
+  created_at: 2015-01-01T00:00:00.123456Z
+  modified_at: 2015-01-01T00:00:00.123456Z
 
 repository4:
   uuid: zzzzz-s0uqq-38oru8hnk57ht34
   owner_uuid: zzzzz-tpzed-d9tiejq69daie8f # admin user
   name: foo4
+  created_at: 2015-01-01T00:00:00.123456Z
+  modified_at: 2015-01-01T00:00:00.123456Z
 
 auto_setup_repository:
   uuid: zzzzz-s0uqq-382brabc8rp3667
   owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
   name: auto_setup_repo
+  created_at: 2015-01-01T00:00:00.123456Z
+  modified_at: 2015-01-01T00:00:00.123456Z
diff --git a/services/api/test/unit/repository_test.rb b/services/api/test/unit/repository_test.rb
index 327170c..fe99dd4 100644
--- a/services/api/test/unit/repository_test.rb
+++ b/services/api/test/unit/repository_test.rb
@@ -1,7 +1,13 @@
 require 'test_helper'
 
 class RepositoryTest < ActiveSupport::TestCase
-  # test "the truth" do
-  #   assert true
-  # end
+  test 'write permission allows changing modified_at' do
+    act_as_user users(:active) do
+      r = repositories(:foo)
+      modtime_was = r.modified_at
+      r.modified_at = Time.now
+      assert r.save
+      assert_operator modtime_was, :<, r.modified_at
+    end
+  end
 end

commit c106899198b67d1071ccf164ce743b651981f8cd
Author: Tom Clegg <tom at curoverse.com>
Date:   Mon Mar 16 16:27:06 2015 -0400

    5416: Add integration tests.

diff --git a/services/arv-git-httpd/auth_handler.go b/services/arv-git-httpd/auth_handler.go
index f182bca..3d29993 100644
--- a/services/arv-git-httpd/auth_handler.go
+++ b/services/arv-git-httpd/auth_handler.go
@@ -13,10 +13,6 @@ import (
 )
 
 func newArvadosClient() interface{} {
-	// MakeArvadosClient returns an error if token is unset (even
-	// though we don't need to do anything requiring
-	// authentication yet).
-	os.Setenv("ARVADOS_API_TOKEN", "xxx")
 	arv, err := arvadosclient.MakeArvadosClient()
 	if err != nil {
 		log.Println("MakeArvadosClient:", err)
diff --git a/services/arv-git-httpd/main.go b/services/arv-git-httpd/main.go
index 47758f6..0e92393 100644
--- a/services/arv-git-httpd/main.go
+++ b/services/arv-git-httpd/main.go
@@ -26,6 +26,14 @@ func init() {
 	}
 	flag.StringVar(&theConfig.Root, "repo-root", cwd,
 		"Path to git repositories.")
+
+	// MakeArvadosClient returns an error if token is unset (even
+	// though we don't need to do anything requiring
+	// authentication yet). We can't do this in newArvadosClient()
+	// just before calling MakeArvadosClient(), though, because
+	// that interferes with the env var needed by "run test
+	// servers".
+	os.Setenv("ARVADOS_API_TOKEN", "xxx")
 }
 
 func main() {
diff --git a/services/arv-git-httpd/server.go b/services/arv-git-httpd/server.go
index 393b6c4..716b276 100644
--- a/services/arv-git-httpd/server.go
+++ b/services/arv-git-httpd/server.go
@@ -13,7 +13,7 @@ type server struct {
 	Addr     string // host:port where the server is listening.
 	err      error
 	cond     *sync.Cond
-	done     bool
+	running  bool
 	listener *net.TCPListener
 	wantDown bool
 }
@@ -54,13 +54,14 @@ func (srv *server) Start() error {
 
 	mutex := &sync.RWMutex{}
 	srv.cond = sync.NewCond(mutex.RLocker())
+	srv.running = true
 	go func() {
 		err = srv.Serve(tcpKeepAliveListener{srv.listener})
 		if !srv.wantDown {
 			srv.err = err
 		}
 		mutex.Lock()
-		srv.done = true
+		srv.running = false
 		srv.cond.Broadcast()
 		mutex.Unlock()
 	}()
@@ -69,9 +70,12 @@ func (srv *server) Start() error {
 
 // Wait returns when the server has shut down.
 func (srv *server) Wait() error {
+	if srv.cond == nil {
+		return nil
+	}
 	srv.cond.L.Lock()
 	defer srv.cond.L.Unlock()
-	for !srv.done {
+	for srv.running {
 		srv.cond.Wait()
 	}
 	return srv.err
diff --git a/services/arv-git-httpd/server_test.go b/services/arv-git-httpd/server_test.go
new file mode 100644
index 0000000..c3eed3d
--- /dev/null
+++ b/services/arv-git-httpd/server_test.go
@@ -0,0 +1,152 @@
+package main
+
+import (
+	"errors"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"strings"
+	"testing"
+
+	check "gopkg.in/check.v1"
+	"git.curoverse.com/arvados.git/sdk/go/arvadostest"
+)
+
+var _ = check.Suite(&IntegrationSuite{})
+
+// IntegrationSuite tests need an API server and an arv-git-httpd server
+type IntegrationSuite struct {
+	tmpRepoRoot string
+	tmpWorkdir  string
+	testServer  *server
+}
+
+func (s *IntegrationSuite) TestReadonly(c *check.C) {
+	// Spectator token
+	os.Setenv("ARVADOS_API_TOKEN", "zw2f4gwx8hw8cjre7yp6v1zylhrhn3m5gvjq73rtpwhmknrybu")
+	err := s.runGit(c, "fetch", "foo.git")
+	c.Assert(err, check.Equals, nil)
+	err = s.runGit(c, "push", "foo.git", "master:newbranchfail")
+	c.Assert(err, check.ErrorMatches, `.*HTTP code = 403.*`)
+	_, err = os.Stat(s.tmpRepoRoot + "/.git/refs/heads/newbranchfail")
+	c.Assert(err, check.FitsTypeOf, &os.PathError{})
+}
+
+func (s *IntegrationSuite) TestReadwrite(c *check.C) {
+	// Active user token
+	os.Setenv("ARVADOS_API_TOKEN", "3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi")
+	err := s.runGit(c, "fetch", "foo.git")
+	c.Assert(err, check.Equals, nil)
+	err = s.runGit(c, "push", "foo.git", "master:newbranch")
+	c.Assert(err, check.Equals, nil)
+	_, err = os.Stat(s.tmpRepoRoot + "/foo/.git/refs/heads/newbranch")
+	c.Assert(err, check.Equals, nil)
+}
+
+func (s *IntegrationSuite) TestNonexistent(c *check.C) {
+	// Spectator token
+	os.Setenv("ARVADOS_API_TOKEN", "zw2f4gwx8hw8cjre7yp6v1zylhrhn3m5gvjq73rtpwhmknrybu")
+	err := s.runGit(c, "fetch", "thisrepodoesnotexist.git")
+	c.Assert(err, check.ErrorMatches, `.* not found:.*`)
+}
+
+func (s *IntegrationSuite) TestNoPermission(c *check.C) {
+	// Anonymous token
+	os.Setenv("ARVADOS_API_TOKEN", "4kg6k6lzmp9kj4cpkcoxie964cmvjahbt4fod9zru44k4jqdmi")
+	for _, repo := range []string{"foo.git", "foo/.git", "foo/bar.git", "foo/bar/.git"} {
+		err := s.runGit(c, "fetch", repo)
+		c.Assert(err, check.ErrorMatches, `.* not found:.*`)
+	}
+}
+
+func (s *IntegrationSuite) SetUpSuite(c *check.C) {
+	arvadostest.StartAPI()
+}
+
+func (s *IntegrationSuite) SetUpTest(c *check.C) {
+	arvadostest.ResetEnv()
+	s.testServer = &server{}
+	var err error
+	s.tmpRepoRoot, err = ioutil.TempDir("", "arv-git-httpd")
+	c.Assert(err, check.Equals, nil)
+	s.tmpWorkdir, err = ioutil.TempDir("", "arv-git-httpd")
+	c.Assert(err, check.Equals, nil)
+	_, err = exec.Command("git", "init", "--bare", s.tmpRepoRoot + "/arvados.git").Output()
+	c.Assert(err, check.Equals, nil)
+	_, err = exec.Command("git", "--git-dir", s.tmpRepoRoot + "/arvados.git", "fetch", "../../.git", "master:master").Output()
+	c.Assert(err, check.Equals, nil)
+	_, err = exec.Command("git", "init", s.tmpRepoRoot + "/foo").Output()
+	c.Assert(err, check.Equals, nil)
+	_, err = exec.Command("sh", "-c", "cd " + s.tmpRepoRoot + "/foo && echo test >test && git add test && git commit -am 'foo: test'").CombinedOutput()
+	c.Assert(err, check.Equals, nil)
+	_, err = exec.Command("git", "init", s.tmpWorkdir).Output()
+	c.Assert(err, check.Equals, nil)
+	_, err = exec.Command("sh", "-c", "cd " + s.tmpWorkdir + " && echo work >work && git add work && git commit -am 'workdir: test'").CombinedOutput()
+	c.Assert(err, check.Equals, nil)
+
+	theConfig = &config{
+		Addr: ":",
+		GitCommand: "/usr/bin/git",
+		Root: s.tmpRepoRoot,
+	}
+	err = s.testServer.Start()
+	c.Assert(err, check.Equals, nil)
+
+	// Clear ARVADOS_API_TOKEN after starting up the server, to
+	// make sure arv-git-httpd doesn't use it.
+	os.Setenv("ARVADOS_API_TOKEN", "")
+
+	_, err = exec.Command("git", "config",
+		"--file", s.tmpWorkdir + "/.git/config",
+		"credential.http://" + s.testServer.Addr + "/.helper",
+		"!foo(){ echo password=$ARVADOS_API_TOKEN; };foo").Output()
+	c.Assert(err, check.Equals, nil)
+	_, err = exec.Command("git", "config",
+		"--file", s.tmpWorkdir + "/.git/config",
+		"credential.http://" + s.testServer.Addr + "/.username",
+		"none").Output()
+	c.Assert(err, check.Equals, nil)
+}
+
+func (s *IntegrationSuite) TearDownTest(c *check.C) {
+	var err error
+	if s.testServer != nil {
+		err = s.testServer.Close()
+	}
+	c.Check(err, check.Equals, nil)
+	if s.tmpRepoRoot != "" {
+		err = os.RemoveAll(s.tmpRepoRoot)
+		c.Check(err, check.Equals, nil)
+	}
+	if s.tmpWorkdir != "" {
+		err = os.RemoveAll(s.tmpWorkdir)
+		c.Check(err, check.Equals, nil)
+	}
+}
+
+func (s *IntegrationSuite) runGit(c *check.C, gitCmd, repo string, args ...string) error {
+	cwd, err := os.Getwd()
+	c.Assert(err, check.Equals, nil)
+	defer os.Chdir(cwd)
+	os.Chdir(s.tmpWorkdir)
+
+	gitargs := append([]string{
+		gitCmd, "http://" + s.testServer.Addr + "/" + repo,
+	}, args...)
+	cmd := exec.Command("git", gitargs...)
+	w, err := cmd.StdinPipe()
+	c.Assert(err, check.Equals, nil)
+	go w.Close()
+	output, err := cmd.CombinedOutput()
+	c.Log("git ", gitargs, " => ", err)
+	if err != nil {
+		// Easier to match error strings without newlines.
+		err = errors.New(strings.Replace(string(output), "\n", " // ", -1))
+	}
+	return err
+}
+
+// Gocheck boilerplate
+func Test(t *testing.T) {
+	check.TestingT(t)
+}

commit eb68ddf0ab91faf6ce1dbab4b8db81b56ffeccaf
Author: Tom Clegg <tom at curoverse.com>
Date:   Mon Mar 16 10:18:08 2015 -0400

    5416: Add options to docs.

diff --git a/services/arv-git-httpd/doc.go b/services/arv-git-httpd/doc.go
index 21e8e48..713b018 100644
--- a/services/arv-git-httpd/doc.go
+++ b/services/arv-git-httpd/doc.go
@@ -3,5 +3,27 @@ arv-git-httpd provides authenticated access to Arvados-hosted git repositories.
 
 Example:
 	arv-git-httpd -address=:8000 -repo-root=/var/lib/arvados/git
+
+Options:
+
+	-address [host]:[port]
+
+		Listen at the given host and port. Each can be a name,
+		a number, or empty.
+
+	-repo-root path
+
+		Directory containing git repositories. When a client
+		requests either "foo/bar.git" or "foo/bar/.git",
+		git-http-backend will be invoked on "path/foo/bar.git"
+		or (if that doesn't exist) "path/foo/bar/.git".
+
+	-git-command path
+
+		Location of the CGI program to execute for each
+		authorized request (normally this is git). It is
+		invoked with a single argument, 'http-backend'.
+		Default is /usr/bin/git.
+
 */
 package main

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list