// creates a copy of the authorized_keys and returns it, with the file cursor // pointing at the first byte of the file. func copyFile() (tsurufs.File, error) { path := authKey() fi, statErr := fs.Filesystem().Stat(path) if statErr != nil && !os.IsNotExist(statErr) { return nil, statErr } dstPath := path + ".tmp" dst, err := fs.Filesystem().OpenFile(dstPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return nil, err } if !os.IsNotExist(statErr) { original, err := fs.Filesystem().Open(path) if err != nil { return nil, err } defer original.Close() n, err := io.Copy(dst, original) if err != nil { dst.Close() return nil, err } if n != fi.Size() { dst.Close() return nil, io.ErrShortWrite } dst.Seek(0, 0) } return dst, nil }
func CopyZipFile(f *zip.File, d, p string) error { if p != "" { dirname := path.Dir(p) if dirname != "." { err := os.MkdirAll(path.Join(d, dirname), 0755) if err != nil { return err } } rc, err := f.Open() defer rc.Close() if err != nil { return err } path := path.Join(d, p) stat, err := os.Stat(path) if err != nil || !stat.IsDir() { file, err := fs.Filesystem().OpenFile(path, os.O_WRONLY|os.O_CREATE, 0755) if err != nil { return err } defer file.Close() _, err = io.Copy(file, rc) if err != nil { return err } } } return nil }
// Adds a hook script. func Add(name string, repos []string, content []byte) error { configParam := "git:bare:template" if len(repos) > 0 { configParam = "git:bare:location" } path, err := config.GetString(configParam) if err != nil { return err } s := []string{path, "hooks", name} scriptPath := strings.Join(s, "/") if len(repos) > 0 { for _, repo := range repos { repo += ".git" s = []string{path, repo, "hooks", name} scriptPath = strings.Join(s, "/") err = fs.Filesystem().MkdirAll(scriptPath+"hooks", 0755) if err != nil { return err } err = createHookFile(scriptPath, content) if err != nil { return err } } } else { return createHookFile(scriptPath, content) } return nil }
func remove(k *Key) error { formatted := k.format() file, err := fs.Filesystem().OpenFile(authKey(), os.O_RDWR|os.O_EXCL, 0644) if err != nil { return err } defer file.Close() lines := make([]string, 0, 10) reader := bufio.NewReader(file) line, _ := reader.ReadString('\n') for line != "" { if line != formatted { lines = append(lines, line) } line, _ = reader.ReadString('\n') } file.Truncate(0) file.Seek(0, 0) content := strings.Join(lines, "") n, err := file.WriteString(content) if err != nil { return err } if n != len(content) { return io.ErrShortWrite } return nil }
// New creates a representation of a git repository. It creates a Git // repository using the "bare-dir" setting and saves repository's meta data in // the database. func New(name string, users []string, isPublic bool) (*Repository, error) { log.Debugf("Creating repository %q", name) r := &Repository{Name: name, Users: users, IsPublic: isPublic} if v, err := r.isValid(); !v { log.Errorf("repository.New: Invalid repository %q: %s", name, err) return r, err } if err := newBare(name); err != nil { log.Errorf("repository.New: Error creating bare repository for %q: %s", name, err) return r, err } barePath := barePath(name) if barePath != "" && isPublic { ioutil.WriteFile(barePath+"/git-daemon-export-ok", []byte(""), 0644) if f, err := fs.Filesystem().Create(barePath + "/git-daemon-export-ok"); err == nil { f.Close() } } conn, err := db.Conn() if err != nil { return nil, err } defer conn.Close() err = conn.Repository().Insert(&r) if mgo.IsDup(err) { log.Errorf("repository.New: Duplicate repository %q", name) return r, fmt.Errorf("A repository with this name already exists.") } return r, err }
// Rename renames a repository. func Rename(oldName, newName string) error { log.Debugf("Renaming repository %q to %q", oldName, newName) repo, err := Get(oldName) if err != nil { log.Errorf("repository.Rename: Repository %q not found: %s", oldName, err) return err } newRepo := repo newRepo.Name = newName conn, err := db.Conn() if err != nil { return err } defer conn.Close() err = conn.Repository().Insert(newRepo) if err != nil { log.Errorf("repository.Rename: Error adding new repository %q: %s", newName, err) return err } err = conn.Repository().RemoveId(oldName) if err != nil { log.Errorf("repository.Rename: Error removing old repository %q: %s", oldName, err) return err } return fs.Filesystem().Rename(barePath(oldName), barePath(newName)) }
func (s *S) authKeysContent(c *gocheck.C) string { authKeysPath := path.Join(os.Getenv("HOME"), ".ssh", "authorized_keys") f, err := fs.Filesystem().OpenFile(authKeysPath, os.O_RDWR|os.O_EXCL, 0755) c.Assert(err, gocheck.IsNil) content, err := ioutil.ReadAll(f) return string(content) }
// New creates a representation of a git repository. It creates a Git // repository using the "bare-dir" setting and saves repository's meta data in // the database. func New(name string, users, readOnlyUsers []string, isPublic bool) (*Repository, error) { log.Debugf("Creating repository %q", name) r := &Repository{Name: name, Users: users, ReadOnlyUsers: readOnlyUsers, IsPublic: isPublic} if v, err := r.isValid(); !v { log.Errorf("repository.New: Invalid repository %q: %s", name, err) return r, err } conn, err := db.Conn() if err != nil { return nil, err } defer conn.Close() err = conn.Repository().Insert(r) if err != nil { if mgo.IsDup(err) { return nil, ErrRepositoryAlreadyExists } return nil, err } if err = newBare(name); err != nil { log.Errorf("repository.New: Error creating bare repository for %q: %s", name, err) conn.Repository().Remove(bson.M{"_id": r.Name}) return r, err } barePath := barePath(name) if barePath != "" && isPublic { if f, createErr := fs.Filesystem().Create(barePath + "/git-daemon-export-ok"); createErr == nil { f.Close() } } return r, err }
func removeBare(name string) error { err := fs.Filesystem().RemoveAll(barePath(name)) if err != nil { return fmt.Errorf("Could not remove git bare repository: %s", err) } return nil }
func (s *S) authKeysContent(c *gocheck.C) string { authFile := path.Join(os.Getenv("HOME"), ".ssh", "authorized_keys") f, err := fs.Filesystem().OpenFile(authFile, os.O_RDWR, 0755) c.Assert(err, gocheck.IsNil) defer f.Close() b, err := ioutil.ReadAll(f) c.Assert(err, gocheck.IsNil) return string(b) }
// writeKeys serializes the given key in the authorized_keys file (of the // current user). func writeKey(k *Key) error { file, err := fs.Filesystem().OpenFile(authKey(), os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644) if err != nil { return err } defer file.Close() syscall.Flock(int(file.Fd()), syscall.LOCK_EX) defer syscall.Flock(int(file.Fd()), syscall.LOCK_UN) return k.dump(file) }
func (s *S) TestCanAddNewHook(c *gocheck.C) { hook_content := strings.NewReader("some content") err := Add("test-can-add-new-hook", []string{}, hook_content) c.Assert(err, gocheck.IsNil) file, err := fs.Filesystem().OpenFile("/home/git/bare-template/hooks/test-can-add-new-hook", os.O_RDONLY, 0755) defer file.Close() content, err := ioutil.ReadAll(file) c.Assert(err, gocheck.IsNil) c.Assert(string(content), gocheck.Equals, "some content") }
func (s *S) TestCanCreateHookFile(c *gocheck.C) { hook_content := strings.NewReader("some content") err := createHookFile("/tmp/repositories/some-repo.git/hooks/test-can-create-hook-file", hook_content) c.Assert(err, gocheck.IsNil) file, err := fs.Filesystem().OpenFile("/tmp/repositories/some-repo.git/hooks/test-can-create-hook-file", os.O_RDONLY, 0755) defer file.Close() content, err := ioutil.ReadAll(file) c.Assert(err, gocheck.IsNil) c.Assert(string(content), gocheck.Equals, "some content") }
func (s *S) TestCanAddNewRepository(c *gocheck.C) { hook_content := strings.NewReader("some content") err := Add("test-can-add-new-repository-hook", []string{"some-repo"}, hook_content) c.Assert(err, gocheck.IsNil) file, err := fs.Filesystem().OpenFile("/tmp/repositories/some-repo.git/hooks/test-can-add-new-repository-hook", os.O_RDONLY, 0755) defer file.Close() content, err := ioutil.ReadAll(file) c.Assert(err, gocheck.IsNil) c.Assert(string(content), gocheck.Equals, "some content") }
func createHookFile(path string, content []byte) error { file, err := fs.Filesystem().OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755) if err != nil { return err } defer file.Close() _, err = file.Write(content) if err != nil { return err } return nil }
func createHookFile(path string, body io.Reader) error { file, err := fs.Filesystem().OpenFile(path, os.O_WRONLY|os.O_CREATE, 0755) if err != nil { return err } defer file.Close() _, err = io.Copy(file, body) if err != nil { return err } return nil }
func (s *S) TestAddUpdateReceiveHookRepository(c *gocheck.C) { b := strings.NewReader(`{"repositories": ["some-repo"], "content": "some content"}`) recorder, request := post("repository/hook/update?:name=update", b, c) AddHook(recorder, request) got := readBody(recorder.Body, c) expected := "hook update successfully created for [some-repo]\n" c.Assert(got, gocheck.Equals, expected) c.Assert(recorder.Code, gocheck.Equals, 200) file, err := fs.Filesystem().OpenFile("/tmp/repositories/some-repo.git/hooks/update", os.O_RDONLY, 0755) defer file.Close() content, err := ioutil.ReadAll(file) c.Assert(err, gocheck.IsNil) c.Assert(string(content), gocheck.Equals, "some content") }
func (s *S) TestAddUpdateOldFormatHook(c *gocheck.C) { b := strings.NewReader("some content") recorder, request := post("/hook/update?:name=update", b, c) AddHook(recorder, request) got := readBody(recorder.Body, c) expected := "hook update successfully created\n" c.Assert(got, gocheck.Equals, expected) c.Assert(recorder.Code, gocheck.Equals, 200) file, err := fs.Filesystem().OpenFile("/home/git/bare-template/hooks/update", os.O_RDONLY, 0755) defer file.Close() content, err := ioutil.ReadAll(file) c.Assert(err, gocheck.IsNil) c.Assert(string(content), gocheck.Equals, "some content") }
func (s *S) TestCanAddNewHookInOldRepository(c *check.C) { s.rfs = &fstest.RecordingFs{} fs.Fsystem = s.rfs bareTemplate, _ := config.GetString("git:bare:template") err := fs.Fsystem.RemoveAll(bareTemplate + "/hooks") c.Assert(err, check.IsNil) hookContent := []byte("some content") err = Add("test-can-add-new-hook", []string{}, hookContent) c.Assert(err, check.IsNil) file, err := fs.Filesystem().OpenFile("/home/git/bare-template/hooks/test-can-add-new-hook", os.O_RDONLY, 0755) defer file.Close() content, err := ioutil.ReadAll(file) c.Assert(err, check.IsNil) c.Assert(string(content), check.Equals, "some content") }
// Adds a hook script. func Add(name string, body io.ReadCloser) error { path, err := config.GetString("git:bare:template") if err != nil { return err } s := []string{path, "hooks", name} scriptPath := strings.Join(s, "/") file, err := fs.Filesystem().OpenFile(scriptPath, os.O_WRONLY|os.O_CREATE, 0755) if err != nil { return err } defer file.Close() _, err = io.Copy(file, body) if err != nil { return err } return nil }
// Update update a repository data. func Update(name string, newData Repository) error { log.Debugf("Updating repository %q data", name) repo, err := Get(name) if err != nil { log.Errorf("repository.Update(%q): %s", name, err) return err } conn, err := db.Conn() if err != nil { return err } defer conn.Close() if len(newData.Name) > 0 && newData.Name != repo.Name { oldName := repo.Name log.Debugf("Renaming repository %q to %q", oldName, newData.Name) err = conn.Repository().Insert(newData) if err != nil { log.Errorf("repository.Rename: Error adding new repository %q: %s", newData.Name, err) return err } err = conn.Repository().RemoveId(oldName) if err != nil { log.Errorf("repository.Rename: Error removing old repository %q: %s", oldName, err) return err } err = fs.Filesystem().Rename(barePath(oldName), barePath(newData.Name)) if err != nil { log.Errorf("repository.Rename: Error renaming old repository in filesystem %q: %s", oldName, err) return err } } else { err = conn.Repository().UpdateId(repo.Name, newData) if err != nil { log.Errorf("repository.Update: Error updating repository data %q: %s", repo.Name, err) return err } } return nil }
// moveFile writes the authorized key file atomically. func moveFile(fromPath string) error { return fs.Filesystem().Rename(fromPath, authKey()) }