internal/ci/paths.go
67 lines · 1816 bytes
4 symbols in this file
1package ci
2
3import (
4 "path"
5 "strings"
6)
7
8// zeroSHA is git's null object id: the old side of a ref update that
9// created the ref, carrying no diff base.
10const zeroSHA = "0000000000000000000000000000000000000000"
11
12// Match reports whether a changed file path matches a job's glob.
13// A trailing /** matches the directory and everything below it at any
14// depth; anything else goes to path.Match, whose * stops at a separator.
15func Match(pattern, file string) bool {
16 if prefix, ok := strings.CutSuffix(pattern, "/**"); ok {
17 return file == prefix || strings.HasPrefix(file, prefix+"/")
18 }
19 ok, err := path.Match(pattern, file)
20 return err == nil && ok
21}
22
23// Selected reports whether a job's path filters admit a push that
24// changed the given files. Call it only once the changed-file list is
25// known; a caller that cannot compute one must run the job instead of
26// calling this.
27//
28// The job runs when Paths is empty or at least one file matches one of
29// its patterns, and is then held back only if PathsIgnore is non-empty
30// and every file matches one of its patterns.
31func Selected(j Job, files []string) bool {
32 if len(j.Paths) > 0 {
33 hit := false
34 for _, f := range files {
35 for _, p := range j.Paths {
36 if Match(p, f) {
37 hit = true
38 }
39 }
40 }
41 if !hit {
42 return false
43 }
44 }
45 if len(j.PathsIgnore) > 0 {
46 for _, f := range files {
47 ignored := false
48 for _, p := range j.PathsIgnore {
49 if Match(p, f) {
50 ignored = true
51 }
52 }
53 if !ignored {
54 return true
55 }
56 }
57 return false
58 }
59 return true
60}
61
62// HasDiffBase reports whether old names a commit a diff can start from.
63// A branch's first push carries an empty or all-zero old sha, so there
64// is nothing to compare the new commit against.
65func HasDiffBase(old string) bool {
66 return old != "" && old != zeroSHA
67}