// @return result.Result<VersionStatus, error> func writeVersion(repo *git.Repository, version string) result.Result { oid := result.NewResult(repo.CreateBlobFromBuffer([]byte(version))) return oid.FlatMap(func(oid interface{}) result.Result { path := filepath.Join(gg.CommentRefBase, versionRef) return result.NewResult(repo.References.Create(path, oid.(*git.Oid), false, upgradeMessage)) }).FlatMap(func(ref interface{}) result.Result { return result.NewSuccess(VersionStatusEqual) }) }
// @return result.Result<VersionStatus, error> func compareVersion(toolVersion, repoVersion string) result.Result { errorMsg := fmt.Sprintf(toolInvalidError, toolVersion, repoVersion) invalidErr := result.NewFailure(errors.New(errorMsg)) vt := result.NewResult(semver.Make(toolVersion)).RecoverWith(invalidErr) vr := result.NewResult(semver.Make(repoVersion)).RecoverWith(invalidErr) return result.Combine(func(values ...interface{}) result.Result { vt, vr := values[0].(semver.Version), values[1].(semver.Version) return comparisonStatus(vt.Compare(vr)) }, vt, vr) }
// @return result.Result<string, error> func readVersion(repo *git.Repository) result.Result { path := filepath.Join(gg.CommentRefBase, versionRef) ref := result.NewResult(repo.References.Lookup(path)) return ref.FlatMap(func(ref interface{}) result.Result { oid := ref.(*git.Reference).Target() return result.NewResult(repo.LookupBlob(oid)) }).FlatMap(func(blob interface{}) result.Result { contents := blob.(*git.Blob).Contents() return result.NewSuccess(string(contents)) }) }
// Open or create a search index // @return result.Result<bleve.Index, error> func openIndex(repoPath string, ifSuccess func(*git.Repository, bleve.Index) result.Result) result.Result { storage := filepath.Join(repoPath, gc.CommentStorageDir) indexPath := filepath.Join(storage, indexFilePath) return gg.WithRepository(repoPath, func(repo *git.Repository) result.Result { os.Mkdir(storage, 0700) success := func(index interface{}) result.Result { return ifSuccess(repo, index.(bleve.Index)) } return result.NewResult(bleve.Open(indexPath)).Analysis(success, func(err error) result.Result { mapping := bleve.NewIndexMapping() index := result.NewResult(bleve.New(indexPath, mapping)) return index.FlatMap(success) }) }) }
// Lookup a remote by name, performing a block if found // @return result.Result<*git.Remote, error> func WithRemote(repoPath, remoteName string, ifSuccess func(*git.Remote) result.Result) result.Result { return WithRepository(repoPath, func(repo *git.Repository) result.Result { return result.NewResult(repo.Remotes.Lookup(remoteName)) }).FlatMap(func(remote interface{}) result.Result { return ifSuccess(remote.(*git.Remote)) }) }
func WithConfig(repoPath string, ifSuccess func(config *git.Config) result.Result) result.Result { return WithRepository(repoPath, func(repo *git.Repository) result.Result { return result.NewResult(repo.Config()) }).FlatMap(func(config interface{}) result.Result { return ifSuccess(config.(*git.Config)) }) }
// Add a fetch refspec to a remote. Return true if added. // @return result.Result<bool, error> func AddFetch(repo *git.Repository, remote *git.Remote, fetchRef string) result.Result { f := result.NewResult(remote.FetchRefspecs()) return f.FlatMap(func(fetches interface{}) result.Result { if !contains(fetches.([]string), fetchRef) { return BoolResult(true, repo.Remotes.AddFetch(remote.Name(), fetchRef)) } return result.NewSuccess(false) }) }
// Add a push refspec to a remote. Return true if added. // @return result.Result<bool, error> func AddPush(repo *git.Repository, remote *git.Remote, pushRef string) result.Result { p := result.NewResult(remote.PushRefspecs()) return p.FlatMap(func(pushes interface{}) result.Result { if !contains(pushes.([]string), pushRef) { return BoolResult(true, repo.Remotes.AddPush(remote.Name(), pushRef)) } return result.NewSuccess(false) }) }
func diffRange(repo *git.Repository, commitRange *gg.CommitRange, contextLines uint32) result.Result { return result.Combine(func(values ...interface{}) result.Result { opts := values[2].(git.DiffOptions) opts.ContextLines = contextLines return result.NewResult(repo.DiffTreeToTree( values[0].(*git.Tree), values[1].(*git.Tree), &opts)) }, commitTree(commitRange.Parent), commitTree(commitRange.Child), diffOptions()) }
func deleteReference(repo *git.Repository, comment *Comment, identifier string) error { _, err := RefPath(comment, identifier).FlatMap(func(refPath interface{}) result.Result { return result.NewResult(repo.References.Lookup(refPath.(string))) }).Analysis(func(ref interface{}) result.Result { return gg.DeleteReference(ref.(*git.Reference)) }, func(err error) result.Result { return result.NewFailure(errors.New(commentNotFoundError)) }).Dematerialize() return err }
// Parse commits from commitish string, populating a CommitRange. If a // single commit is matched, it is paired with its first parent commit // or resolves to an error // // return result.Result<*git.Commit, error> func ResolveCommits(repo *git.Repository, commitish string) result.Result { return result.NewResult(repo.Revparse(commitish)).FlatMap(func(value interface{}) result.Result { spec := value.(*git.Revspec) return resolveCommit(repo, spec.From()).FlatMap(func(f interface{}) result.Result { fromCommit := f.(*git.Commit) return resolveCommit(repo, spec.To()).Analysis(func(t interface{}) result.Result { toCommit := t.(*git.Commit) return result.NewSuccess(&CommitRange{fromCommit, toCommit}) }, func(err error) result.Result { return resolveCommitParent(fromCommit).FlatMap(func(parent interface{}) result.Result { return result.NewSuccess(&CommitRange{parent.(*git.Commit), fromCommit}) }) }) }) }) }
// Find all comments matching text // @return result.Result<[]*Comment, error> func CommentsWithContent(repoPath, content string) result.Result { return openIndex(repoPath, func(repo *git.Repository, index bleve.Index) result.Result { query := bleve.NewQueryStringQuery(content) request := bleve.NewSearchRequest(query) return result.NewResult(index.Search(request)).FlatMap(func(match interface{}) result.Result { hits := match.(*bleve.SearchResult).Hits comments := make([]*gc.Comment, len(hits)) for idx, hit := range hits { gc.CommentByID(repo, hit.ID).FlatMap(func(comment interface{}) result.Result { comments[idx] = comment.(*gc.Comment) return result.Result{} }) } return result.NewSuccess(comments) }) }) }
// Parse a property string and create a person. The expected format is: // ``` // Name <*****@*****.**> // ``` // If a valid person cannot be created, an error is returned instead // @return result.Result<*Person, error> func CreatePerson(properties string) result.Result { fullRe := regexp.MustCompile(`(?:(.*)\s)?<(.*@.*)>(?:\s([0-9]+)\s([\-+][0-9]{4}))?`) match := fullRe.FindStringSubmatch(properties) invalidErr := result.NewFailure(errors.New(invalidPersonError)) if len(match) == 0 { return invalidErr } name, email := match[1], match[2] timestamp := result.NewResult(strconv.ParseInt(match[3], 10, 64)) return timestamp.Analysis(func(value interface{}) result.Result { stamp := time.Unix(value.(int64), 0) person := &Person{match[1], match[2], stamp, match[4]} return result.NewSuccess(person) }, func(err error) result.Result { timestamp := time.Now() return result.NewSuccess(&Person{name, email, timestamp, timestamp.Format("-0700")}) }) }
// Write git object for a given comment and update the // comment refs // @return result.Result<*Comment, error> func writeCommentToDisk(repo *git.Repository, comment *Comment) result.Result { if comment.ID != nil { if err := deleteReference(repo, comment, *comment.ID); err != nil { return result.NewFailure(err) } } return gg.CreateBlob(repo, comment.Serialize()).FlatMap(func(oid interface{}) result.Result { id := fmt.Sprintf("%v", oid) return RefPath(comment, id).FlatMap(func(file interface{}) result.Result { commit := *comment.Commit message := fmt.Sprintf(defaultMessageFormat, commit[:7], id[:7]) return result.NewResult(repo.References.Create(file.(string), oid.(*git.Oid), false, message)) }).FlatMap(func(value interface{}) result.Result { comment.ID = &id return result.NewSuccess(comment) }) }) }
// Parse the commit hash of a single commit from a reference, converting to HEAD // where needed // // return result.Result<*string, error> func ResolveSingleCommitHash(repo *git.Repository, commitish string) result.Result { return result.NewResult(repo.RevparseSingle(ExpandCommitish(commitish))).FlatMap(getObjectId) }
func ConfiguredInt32(repoPath, name string, fallback int32) int32 { return WithConfig(repoPath, func(config *git.Config) result.Result { return result.NewResult(config.LookupInt32(name)) }).Recover(fallback).(int32) }
func resolveCommit(repo *git.Repository, object git.Object) result.Result { if object != nil && object.Type() == git.ObjectCommit { return result.NewResult(repo.LookupCommit(object.Id())) } return result.NewFailure(errors.New(noCommitError)) }
func commitTree(commit *git.Commit) result.Result { return result.NewResult(commit.Tree()) }
// @return result.Result<git.DiffOptions, error> func diffOptions() result.Result { return result.NewResult(git.DefaultDiffOptions()) }
func ConfiguredString(repoPath, name, fallback string) string { return WithConfig(repoPath, func(config *git.Config) result.Result { return result.NewResult(config.LookupString(name)) }).Recover(fallback).(string) }
func ConfiguredBool(repoPath, name string, fallback bool) bool { return WithConfig(repoPath, func(config *git.Config) result.Result { return result.NewResult(config.LookupBool(name)) }).Recover(fallback).(bool) }