github.com/nemith/go-gitlog@v0.0.2-0.20180205151741-6c79beb2287b/gitlog.go (about) 1 // Package gitlog is providing a means to handle git-log. 2 package gitlog 3 4 import ( 5 "os" 6 "path/filepath" 7 8 gitcmd "github.com/tsuyoshiwada/go-gitcmd" 9 ) 10 11 const ( 12 hashField = "HASH" 13 treeField = "TREE" 14 authorField = "AUTHOR" 15 committerField = "COMMITTER" 16 subjectField = "SUBJECT" 17 bodyField = "BODY" 18 tagField = "TAG" 19 20 hashFormat = hashField + ":%H %h" 21 treeFormat = treeField + ":%T %t" 22 authorFormat = authorField + ":%an<%ae>[%at]" 23 committerFormat = committerField + ":%cn<%ce>[%ct]" 24 subjectFormat = subjectField + ":%s" 25 bodyFormat = bodyField + ":%b" 26 tagFormat = tagField + ":%D" 27 28 separator = "@@__GIT_LOG_SEPARATOR__@@" 29 delimiter = "@@__GIT_LOG_DELIMITER__@@" 30 31 logFormat = separator + 32 hashFormat + delimiter + 33 treeFormat + delimiter + 34 authorFormat + delimiter + 35 committerFormat + delimiter + 36 tagFormat + delimiter + 37 subjectFormat + delimiter + 38 bodyFormat 39 ) 40 41 // Config for getting git-log 42 type Config struct { 43 Bin string // default "git" 44 Path string // default "." 45 } 46 47 // Params for getting git-log 48 type Params struct { 49 MergesOnly bool 50 IgnoreMerges bool 51 Reverse bool 52 } 53 54 // GitLog is an interface for git-log acquisition 55 type GitLog interface { 56 Log(RevArgs, *Params) ([]*Commit, error) 57 } 58 59 type gitLogImpl struct { 60 client gitcmd.Client 61 parser *parser 62 config *Config 63 } 64 65 // New GitLog interface 66 func New(config *Config) GitLog { 67 bin := "git" 68 path := "path" 69 70 if config != nil { 71 if config.Bin != "" { 72 bin = config.Bin 73 } 74 75 if config.Path != "" { 76 path = config.Path 77 } 78 } 79 80 return &gitLogImpl{ 81 client: gitcmd.New(&gitcmd.Config{ 82 Bin: bin, 83 }), 84 parser: &parser{}, 85 config: &Config{ 86 Bin: bin, 87 Path: path, 88 }, 89 } 90 } 91 92 // workingdir is go to the temporary working directory 93 func (gitLog *gitLogImpl) workdir() (func() error, error) { 94 cwd, err := filepath.Abs(".") 95 96 back := func() error { 97 return os.Chdir(cwd) 98 } 99 100 if err != nil { 101 return back, err 102 } 103 104 dir, err := filepath.Abs(gitLog.config.Path) 105 if err != nil { 106 return back, err 107 } 108 109 err = os.Chdir(dir) 110 if err != nil { 111 return back, err 112 } 113 114 return back, nil 115 } 116 117 // Build command line args 118 func (gitLog *gitLogImpl) buildArgs(rev RevArgs, params *Params) []string { 119 args := []string{ 120 "--no-decorate", 121 "--pretty=\"" + logFormat + "\"", 122 } 123 124 if params != nil { 125 if params.MergesOnly { 126 args = append(args, "--merges") 127 } 128 129 if params.IgnoreMerges { 130 args = append(args, "--no-merges") 131 } 132 133 if params.Reverse { 134 args = append(args, "--reverse") 135 } 136 } 137 138 if rev != nil { 139 revisions := rev.Args() 140 args = append(args, revisions...) 141 } 142 143 return args 144 } 145 146 // Log internally uses the git command to get a list of git-logs 147 // func (gitLog *gitLogImpl) Log(ref string, rev RevArgs) ([]*Commit, error) { 148 func (gitLog *gitLogImpl) Log(rev RevArgs, params *Params) ([]*Commit, error) { 149 // Can execute the git command? 150 if err := gitLog.client.CanExec(); err != nil { 151 return nil, err 152 } 153 154 // To repository path 155 back, err := gitLog.workdir() 156 if err != nil { 157 return nil, err 158 } 159 defer back() 160 161 // Check inside work tree 162 err = gitLog.client.InsideWorkTree() 163 if err != nil { 164 return nil, err 165 } 166 167 // Dump git-log 168 args := gitLog.buildArgs(rev, params) 169 170 out, err := gitLog.client.Exec("log", args...) 171 if err != nil { 172 return nil, err 173 } 174 175 commits, err := gitLog.parser.parse(&out) 176 if err != nil { 177 return nil, err 178 } 179 180 return commits, nil 181 }