From 3186ef554cdbf54e1a3328ffcb35ea18105d7cb1 Mon Sep 17 00:00:00 2001 From: Mura Li Date: Fri, 12 Apr 2019 10:28:44 +0800 Subject: Support search operators for commits search (#6479) * Support searching commits with prefix syntax For now, support auther: committer: When more than one prefix is supplied is presented, the result is the union. When different prefixes are supplied, the result is the intersection. For example, "author:alice author:bob" => the result is all commits authored by Alice OR Bob "hello committer:alice" => the result is all commits committed by Alice AND has the keyword 'hello' in the message. Note that there should NOT have any space after the colon(:) of the prefix. For example, "author:bill" => correct "author: bill" => wrong * Remove unneeded logging * Add missing files of test repository * Add missing repo_unit entries to test fixtures * Update test cases * Add tooltip for commits search button * Update tooltip text I have no idea about how to format it with line breaks. * Make the usage example more real * Add a test case * Add new options struct for SearchCommits * Prefer len(s) > 0 over s != "" * Add NewSearchCommitsOptions --- modules/git/commit.go | 43 +++++++++++++++++++++++++++++++++++++++++-- modules/git/repo_commit.go | 27 ++++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 5 deletions(-) (limited to 'modules/git') diff --git a/modules/git/commit.go b/modules/git/commit.go index 36b8d54565..85c9554bb5 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -214,9 +214,48 @@ func (c *Commit) CommitsBeforeUntil(commitID string) (*list.List, error) { return c.repo.CommitsBetween(c, endCommit) } +// SearchCommitsOptions specify the parameters for SearchCommits +type SearchCommitsOptions struct { + Keywords []string + Authors, Committers []string + After, Before string + All bool +} + +// NewSearchCommitsOptions contruct a SearchCommitsOption from a space-delimited search string +func NewSearchCommitsOptions(searchString string, forAllRefs bool) SearchCommitsOptions { + var keywords, authors, committers []string + var after, before string + + fields := strings.Fields(searchString) + for _, k := range fields { + switch { + case strings.HasPrefix(k, "author:"): + authors = append(authors, strings.TrimPrefix(k, "author:")) + case strings.HasPrefix(k, "committer:"): + committers = append(committers, strings.TrimPrefix(k, "committer:")) + case strings.HasPrefix(k, "after:"): + after = strings.TrimPrefix(k, "after:") + case strings.HasPrefix(k, "before:"): + before = strings.TrimPrefix(k, "before:") + default: + keywords = append(keywords, k) + } + } + + return SearchCommitsOptions{ + Keywords: keywords, + Authors: authors, + Committers: committers, + After: after, + Before: before, + All: forAllRefs, + } +} + // SearchCommits returns the commits match the keyword before current revision -func (c *Commit) SearchCommits(keyword string, all bool) (*list.List, error) { - return c.repo.searchCommits(c.ID, keyword, all) +func (c *Commit) SearchCommits(opts SearchCommitsOptions) (*list.List, error) { + return c.repo.searchCommits(c.ID, opts) } // GetFilesChangedSinceCommit get all changed file names between pastCommit to current revision diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index 146619373d..1ecd1f8891 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -237,9 +237,30 @@ func (repo *Repository) commitsByRange(id SHA1, page int) (*list.List, error) { return repo.parsePrettyFormatLogToList(stdout) } -func (repo *Repository) searchCommits(id SHA1, keyword string, all bool) (*list.List, error) { - cmd := NewCommand("log", id.String(), "-100", "-i", "--grep="+keyword, prettyLogFormat) - if all { +func (repo *Repository) searchCommits(id SHA1, opts SearchCommitsOptions) (*list.List, error) { + cmd := NewCommand("log", id.String(), "-100", "-i", prettyLogFormat) + if len(opts.Keywords) > 0 { + for _, v := range opts.Keywords { + cmd.AddArguments("--grep=" + v) + } + } + if len(opts.Authors) > 0 { + for _, v := range opts.Authors { + cmd.AddArguments("--author=" + v) + } + } + if len(opts.Committers) > 0 { + for _, v := range opts.Committers { + cmd.AddArguments("--committer=" + v) + } + } + if len(opts.After) > 0 { + cmd.AddArguments("--after=" + opts.After) + } + if len(opts.Before) > 0 { + cmd.AddArguments("--before=" + opts.Before) + } + if opts.All { cmd.AddArguments("--all") } stdout, err := cmd.RunInDirBytes(repo.Path) -- cgit v1.2.3