diff --git a/server.go b/server.go index b88b833..787dfcb 100644 --- a/server.go +++ b/server.go @@ -31,6 +31,10 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { return } p.Path = fmt.Sprintf("%s/%s", s.hostname, strings.Trim(req.URL.Path, "/")) + if !Valid(p.Path, s.storage.All()) { + http.Error(w, fmt.Sprintf("invalid path; prefix already taken %q", req.URL.Path), http.StatusConflict) + return + } s.storage.Add(p) case "PATCH": default: diff --git a/storage.go b/storage.go index 698b6c5..e63d33f 100644 --- a/storage.go +++ b/storage.go @@ -2,9 +2,19 @@ package vain import ( "errors" + "strings" "sync" ) +func Valid(p string, packages []Package) bool { + for _, pkg := range packages { + if strings.HasPrefix(pkg.Path, p) { + return false + } + } + return true +} + type MemStore struct { l sync.RWMutex p map[string]Package diff --git a/vain_test.go b/vain_test.go index 1690969..270546c 100644 --- a/vain_test.go +++ b/vain_test.go @@ -35,3 +35,60 @@ func TestVcsStrings(t *testing.T) { } } } + +func TestValid(t *testing.T) { + tests := []struct { + pkgs []Package + in string + want bool + }{ + { + pkgs: []Package{}, + in: "bobo", + want: true, + }, + { + pkgs: []Package{ + {Path: ""}, + }, + in: "bobo", + want: true, + }, + { + pkgs: []Package{ + {Path: "bobo"}, + }, + in: "bobo", + want: false, + }, + { + pkgs: []Package{ + {Path: "a/b/c"}, + }, + in: "a/b/c", + want: false, + }, + { + pkgs: []Package{ + {Path: "foo/bar"}, + {Path: "foo/baz"}, + }, + in: "foo", + want: false, + }, + { + pkgs: []Package{ + {Path: "bilbo"}, + {Path: "frodo"}, + }, + in: "foo/bar/baz", + want: true, + }, + } + for _, test := range tests { + got := Valid(test.in, test.pkgs) + if got != test.want { + t.Errorf("Incorrect testing of %q against %#v; got %t, want %t", test.in, test.pkgs, got, test.want) + } + } +}