github.com/benchkram/bob@v0.0.0-20240314204020-b7a57f2f9be9/bobgit/pathspec/pathspec.go (about) 1 package pathspec 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/benchkram/bob/pkg/filepathutil" 8 ) 9 10 // map the repo as key and pathspec as value 11 // 12 // where repository is relative to the bobroot 13 // and pathspec is relative to the repository. 14 type RepoPathspecMap map[string]string 15 16 var ErrRepoNotFound = fmt.Errorf("Repository name not found in target path repository list") 17 18 // P, stores the pathspec attribute for git 19 // intended to be used for the multi repo case. 20 type P struct { 21 path string 22 possibleRepos RepoPathspecMap 23 } 24 25 func New(path string) *P { 26 at := &P{ 27 path: path, 28 possibleRepos: ComputePossibleRepos(path), 29 } 30 31 return at 32 } 33 34 // SelectReposByPath filter the repos from all the repository list 35 // by the pathspec where git add command will be executed. 36 // 37 // Select all repos in case of target "." and set pathspecc 38 // to "." for all repos. 39 func (p *P) SelectReposByPath(repolist []string) []string { 40 // return all the possible repos in case of 41 // all `.` 42 if p.path == "." || p.path == "./" { 43 for _, repo := range repolist { 44 if repo != "." { 45 p.possibleRepos[repo] = "." 46 } 47 } 48 return repolist 49 } 50 51 filterd := []string{} 52 for _, repo := range repolist { 53 for r := range p.possibleRepos { 54 if repo == r { 55 filterd = append(filterd, repo) 56 } 57 } 58 } 59 60 // get filtered repos from the target path 61 filterd = removeParentRepos(filterd) 62 63 // add all possible repositories that situated 64 // in the target directory if path ends with `.` 65 if strings.Contains(p.path, "/.") { 66 for _, repo := range repolist { 67 if !contains(filterd, repo) { 68 temptarget := strings.Trim(p.path, ".") 69 if strings.HasPrefix(repo, temptarget) { 70 filterd = append(filterd, repo) 71 p.possibleRepos[repo] = "." 72 } 73 } 74 } 75 } 76 77 return filterd 78 } 79 80 // GetRelativePathspec returns the relative pathspec from the internal map. 81 func (p *P) GetRelativePathspec(reponame string) (string, error) { 82 if val, ok := p.possibleRepos[reponame]; ok { 83 return val, nil 84 } 85 return "", ErrRepoNotFound 86 } 87 88 // ComputePossibleRepos Compute all the possible repository path 89 // from the provided path starting from bobroot inside bob workspace 90 // and returns a map of string where key is repository path and value is 91 // the relative path from that repository. 92 // 93 // repositories can be filtered later from the computed repository paths. 94 // 95 // Example: 96 // 97 // 'bobroot/sample/path' => {".": 'bobroot/sample/path', 98 // "bobroot": 'sample/path', "bobroot/sample": 'path', ..} 99 // 100 // can be interpreted this way, if the selected repository path is `bobroot/sample`, 101 // then pathspec for that target path would be only `path`, and so on. 102 func ComputePossibleRepos(path string) RepoPathspecMap { 103 104 possibleRepos := make(RepoPathspecMap) 105 possibleRepos["."] = path 106 107 if path == "." { 108 return possibleRepos 109 } 110 111 splitted := strings.Split(path, "/") 112 113 for i := 0; i < len(splitted)-1; i++ { 114 repo := strings.Join(splitted[:i+1], "/") 115 target := strings.Join(splitted[i+1:], "/") 116 possibleRepos[repo] = target 117 } 118 possibleRepos[strings.Join(splitted, "/")] = "." 119 120 return possibleRepos 121 } 122 123 // removeParentRepos removes the parent repository path from each 124 // repo in `repolist`. Keeping only the child repository path. 125 func removeParentRepos(repolist []string) []string { 126 filtered := []string{} 127 for _, repo := range repolist { 128 hasChild := false 129 for _, r := range repolist { 130 if r != repo { 131 hasChild = filepathutil.IsChild(repo, r) 132 } 133 } 134 if !hasChild { 135 filtered = append(filtered, repo) 136 } 137 } 138 return filtered 139 } 140 141 // contains returns true when e is contained in s 142 func contains(s []string, e string) bool { 143 for _, a := range s { 144 if a == e { 145 return true 146 } 147 } 148 return false 149 }