Example #1
0
func resolveCommitParent(commit *git.Commit) result.Result {
	parent := commit.Parent(0)
	if parent == nil {
		return result.NewFailure(errors.New(noParentError))
	}
	return result.NewSuccess(parent)
}
Example #2
0
// 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})
				})
			})
		})
	})
}
Example #3
0
// Count comments on commit
// @return result.Result<uint16, error>
func CommentCountOnCommit(repo *git.Repository, commit string) result.Result {
	var count uint16 = 0
	return gg.CommitCommentRefIterator(repo, commit, func(ref *git.Reference) {
		count += 1
	}).FlatMap(func(value interface{}) result.Result {
		return result.NewSuccess(count)
	})
}
Example #4
0
// 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)
	})
}
Example #5
0
// 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")})
	})
}
Example #6
0
// Finds a comment by ID
// @return result.Result<*Comment, error>
func CommentByID(repo *git.Repository, identifier string) result.Result {
	return gg.LookupBlob(repo, identifier, commentNotFoundError).FlatMap(func(blob interface{}) result.Result {
		return DeserializeComment(string(blob.(*git.Blob).Contents()))
	}).FlatMap(func(c interface{}) result.Result {
		comment := c.(*Comment)
		comment.ID = &identifier
		return result.NewSuccess(comment)
	})
}
Example #7
0
func (p *Printer) PrintCommentsMatching(wd, text string) result.Result {
	return CommentsWithContent(wd, text).FlatMap(func(matches interface{}) result.Result {
		for _, comment := range matches.([]*gc.Comment) {
			p.pager.AddContent(p.formatter.FormatComment(comment, text))
		}
		p.pager.Finish()
		return result.NewSuccess(true)
	})
}
Example #8
0
// 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)
	})
}
Example #9
0
func comparisonStatus(code int) result.Result {
	switch code {
	case -1:
		return result.NewFailure(errors.New(upgradeToolError))
	case 1:
		return result.NewFailure(errors.New(upgradeRepoError))
	default:
		return result.NewSuccess(VersionStatusEqual)
	}
}
Example #10
0
// @return result.Result<*Diff, error>
func diffCommits(repo *git.Repository, commitRange *gg.CommitRange, contextLines uint32) result.Result {
	comments := CommentsOnCommits(repo, commitRange.Commits())
	diff := diffRange(repo, commitRange, contextLines)
	return result.Combine(func(values ...interface{}) result.Result {
		parentID := commitRange.Parent.Id().String()
		childID := commitRange.Child.Id().String()
		files := parseDiffForLines(values[0].(*git.Diff), values[1].(CommentSlice))
		return result.NewSuccess(&Diff{files, parentID, childID})
	}, diff, comments)
}
Example #11
0
// @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)
	})
}
Example #12
0
func validatedCommitForComment(repo *git.Repository, commit string) result.Result {
	return gg.ResolveSingleCommitHash(repo, commit).FlatMap(func(hash interface{}) result.Result {
		return CommentCountOnCommit(repo, *(hash.(*string))).FlatMap(func(count interface{}) result.Result {
			if count.(uint16) >= maxCommentsOnCommit {
				return result.NewFailure(errors.New(maxCommentError))
			}
			return result.NewSuccess(hash)
		})
	})
}
Example #13
0
// @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))
	})
}
Example #14
0
// Finds all comments on a commit
// @return result.Result<[]*Comment, error>
func commentsOnCommit(repo *git.Repository, commit *git.Commit) result.Result {
	var comments []interface{}
	return gg.CommitCommentRefIterator(repo, commit.Id().String(), func(ref *git.Reference) {
		CommentFromRef(repo, ref.Name()).FlatMap(func(comment interface{}) result.Result {
			comments = append(comments, comment)
			return result.Result{}
		})
	}).FlatMap(func(value interface{}) result.Result {
		return result.NewSuccess(comments)
	})
}
Example #15
0
func DeserializeComment(content string) result.Result {
	const serializationErrorMessage = "Could not deserialize object into comment"
	blob := CreatePropertyBlob(content)
	comment := &Comment{}
	comment.Content = blob.Message
	comment.Commit = blob.Get(commitKey)
	comment.Author = blob.GetPerson(authorKey)
	comment.Amender = blob.GetPerson(amenderKey)
	comment.FileRef = blob.GetFileRef(fileRefKey)
	return result.NewSuccess(comment)
}
Example #16
0
// Configure a remote to fetch and push comment changes by default
// @return result.Result<bool, error>
func ConfigureRemoteForComments(repoPath, remoteName string) result.Result {
	return gg.WithRemote(repoPath, remoteName, func(remote *git.Remote) result.Result {
		success := func(values ...interface{}) result.Result {
			return result.NewSuccess(true)
		}
		return gg.WithRepository(repoPath, func(repo *git.Repository) result.Result {
			pushRef := commentDefaultPush
			fetchRef := fmt.Sprintf(commentDefaultFetch, remoteName)
			return result.Combine(success, gg.AddPush(repo, remote, pushRef), gg.AddFetch(repo, remote, fetchRef))
		})
	})
}
Example #17
0
// Create a new comment on a commit, optionally with a file and line
// @return result.Result<*string, error>
func CreateComment(repoPath, commit, author, message string, fileRef *FileRef) result.Result {
	return gg.WithRepository(repoPath, func(repo *git.Repository) result.Result {
		return validatedCommitForComment(repo, commit).FlatMap(func(hash interface{}) result.Result {
			return commentAuthor(repoPath, author).FlatMap(func(author interface{}) result.Result {
				return NewComment(message, *(hash).(*string), fileRef, author.(*Person))
			}).FlatMap(func(value interface{}) result.Result {
				comment := value.(*Comment)
				success := writeCommentToDisk(repo, comment)
				return success.FlatMap(func(value interface{}) result.Result {
					return result.NewSuccess(comment.ID)
				})
			})
		})
	})
}
Example #18
0
// Finds all comments on an array of commits
// @return result.Result<[]*Comment, error>
func CommentsOnCommits(repo *git.Repository, commits []*git.Commit) result.Result {
	results := make([]result.Result, len(commits))
	for index, commit := range commits {
		results[index] = commentsOnCommit(repo, commit)
	}
	return result.Combine(func(values ...interface{}) result.Result {
		comments := make(CommentSlice, 0)
		for _, list := range values {
			for _, comment := range list.([]interface{}) {
				comments = append(comments, comment.(*Comment))
			}
		}
		sort.Stable(comments)
		return result.NewSuccess(comments)
	}, results...)
}
Example #19
0
// 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)
		})
	})
}
Example #20
0
// @return result.Result<bool, error>
func IndexComments(repoPath string) result.Result {
	return openIndex(repoPath, func(repo *git.Repository, index bleve.Index) result.Result {
		results := make([]result.Result, 0)
		batch := index.NewBatch()
		return gg.CommentRefIterator(repo, func(ref *git.Reference) {
			gc.CommentFromRef(repo, ref.Name()).FlatMap(func(c interface{}) result.Result {
				comment := c.(*gc.Comment)
				err := batch.Index(*comment.ID, commentIndex(comment))
				results = append(results, gg.BoolResult(true, err))
				return result.NewSuccess(true)
			})
		}).FlatMap(func(value interface{}) result.Result {
			return result.Combine(func(values ...interface{}) result.Result {
				return gg.BoolResult(true, index.Batch(batch))
			}, results...)
		})
	})
}
Example #21
0
// 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)
		})
	})
}
Example #22
0
// Creates a new comment using provided content and author
func NewComment(message string, commit string, fileRef *FileRef, author *Person) result.Result {
	const missingContentMessage = "No message content provided"
	const missingCommitMessage = "No commit provided"
	if len(message) == 0 {
		return result.NewFailure(errors.New(missingContentMessage))
	} else if len(commit) == 0 {
		return result.NewFailure(errors.New(missingCommitMessage))
	}
	return result.NewSuccess(&Comment{
		author,
		message,
		author,
		&commit,
		nil,
		false,
		fileRef,
	})
}
Example #23
0
// Converts an error into a failure result,
// or nil into a success result
func BoolResult(value bool, err error) result.Result {
	if err != nil {
		return result.NewFailure(err)
	}
	return result.NewSuccess(value)
}
Example #24
0
// Generate the path within refs for a given comment
//
// Comment refs are nested under refs/comments. The
// format is as follows:
//
// ```
// refs/comments/[<commit prefix>]/[<rest of commit>]/[<comment id>]
// ```
//
// @return result.Result<string, error>
func RefPath(comment *Comment, identifier string) result.Result {
	return gg.CommitRefDir(*comment.Commit).FlatMap(func(dir interface{}) result.Result {
		return result.NewSuccess(path.Join(dir.(string), identifier))
	})
}
Example #25
0
func getObjectId(value interface{}) result.Result {
	id := value.(git.Object).Id().String()
	return result.NewSuccess(&id)
}