@@ -54,13 +54,29 @@ var credentialHelper = &cobra.Command{
54
54
fmt .Printf ("username=%s\n password=%s\n " , user , token )
55
55
}()
56
56
57
- gitCommandData := parseProcessTree ()
58
- if gitCommandData == nil {
57
+ gitCmdInfo := & gitCommandInfo {}
58
+ err = walkProcessTree (os .Getpid (), func (pid int ) bool {
59
+ cmdLine , err := readProc (pid , "cmdline" )
60
+ if err != nil {
61
+ log .WithError (err ).Print ("error reading proc cmdline" )
62
+ return true
63
+ }
64
+
65
+ cmdLineString := strings .ReplaceAll (cmdLine , string (byte (0 )), " " )
66
+ gitCmdInfo .parseGitCommandAndOriginRemote (cmdLineString )
67
+
68
+ return gitCmdInfo .Ok ()
69
+ })
70
+ if err != nil {
71
+ log .WithError (err ).Print ("error walking process tree" )
72
+ return
73
+ }
74
+ if ! gitCmdInfo .Ok () {
59
75
return
60
76
}
61
77
62
78
// Starts another process which tracks the executed git event
63
- gitCommandTracker := exec .Command ("/proc/self/exe" , "git-track-command" , "--gitCommand" , gitCommandData .GitCommand )
79
+ gitCommandTracker := exec .Command ("/proc/self/exe" , "git-track-command" , "--gitCommand" , gitCmdInfo .GitCommand )
64
80
err = gitCommandTracker .Start ()
65
81
if err != nil {
66
82
log .WithError (err ).Print ("error spawning tracker" )
@@ -98,7 +114,7 @@ var credentialHelper = &cobra.Command{
98
114
99
115
validator := exec .Command ("/proc/self/exe" , "git-token-validator" ,
100
116
"--user" , resp .User , "--token" , resp .Token , "--scopes" , strings .Join (resp .Scope , "," ),
101
- "--host" , host , "--repoURL" , gitCommandData .RepoUrl , "--gitCommand" , gitCommandData .GitCommand )
117
+ "--host" , host , "--repoURL" , gitCmdInfo .RepoUrl , "--gitCommand" , gitCmdInfo .GitCommand )
102
118
err = validator .Start ()
103
119
if err != nil {
104
120
log .WithError (err ).Print ("error spawning validator" )
@@ -134,85 +150,101 @@ func parseHostFromStdin() string {
134
150
return host
135
151
}
136
152
137
- func parseProcessTree () ( result * struct {
153
+ type gitCommandInfo struct {
138
154
RepoUrl string
139
155
GitCommand string
140
- }) {
141
- gitCommandRegExp := regexp .MustCompile (`git(,\d+\s+|\s+)(push|clone|fetch|pull|diff)` )
142
- repoUrlRegExp := regexp .MustCompile (`\sorigin\s*(https:[^\s]*)\s` )
143
- pid := os .Getpid ()
144
- for {
145
- cmdLine := readProc (pid , "cmdline" )
146
- if cmdLine == "" {
147
- return
148
- }
149
- cmdLineString := strings .ReplaceAll (cmdLine , string (byte (0 )), " " )
156
+ }
150
157
151
- var gitCommand string
152
- matchCommand := gitCommandRegExp .FindStringSubmatch (cmdLineString )
153
- if len (matchCommand ) == 3 {
154
- gitCommand = matchCommand [2 ]
155
- }
158
+ func (g * gitCommandInfo ) Ok () bool {
159
+ return g .RepoUrl != "" && g .GitCommand != ""
160
+ }
156
161
157
- var repoUrl string
158
- matchRepo := repoUrlRegExp .FindStringSubmatch (cmdLineString )
159
- if len (matchRepo ) == 2 {
160
- repoUrl = matchRepo [1 ]
161
- if ! strings .HasSuffix (repoUrl , ".git" ) {
162
- repoUrl = repoUrl + ".git"
163
- }
164
- }
162
+ var gitCommandRegExp = regexp .MustCompile (`git(,\d+\s+|\s+)(push|clone|fetch|pull|diff)` )
163
+ var repoUrlRegExp = regexp .MustCompile (`\sorigin\s*(https:[^\s]*)\s` )
164
+
165
+ // This method needs to be called multiple times to fill all the required info
166
+ // from different git commands
167
+ // For example from first command below the `RepoUrl` will be parsed and from
168
+ // the second command the `GitCommand` will be parsed
169
+ // `/usr/lib/git-core/git-remote-https origin https://github.com/jeanp413/test-gp-bug.git`
170
+ // `/usr/lib/git-core/git push`
171
+ func (g * gitCommandInfo ) parseGitCommandAndOriginRemote (cmdLineString string ) {
172
+ matchCommand := gitCommandRegExp .FindStringSubmatch (cmdLineString )
173
+ if len (matchCommand ) == 3 {
174
+ g .GitCommand = matchCommand [2 ]
175
+ }
165
176
166
- if repoUrl != "" && gitCommand != "" {
167
- result = & struct {
168
- RepoUrl string
169
- GitCommand string
170
- }{
171
- RepoUrl : repoUrl ,
172
- GitCommand : gitCommand ,
173
- }
174
- return
177
+ matchRepo := repoUrlRegExp .FindStringSubmatch (cmdLineString )
178
+ if len (matchRepo ) == 2 {
179
+ g .RepoUrl = matchRepo [1 ]
180
+ if ! strings .HasSuffix (g .RepoUrl , ".git" ) {
181
+ g .RepoUrl = g .RepoUrl + ".git"
175
182
}
183
+ }
184
+ }
176
185
177
- statsString := readProc (pid , "stat" )
178
- if statsString == "" {
179
- return
180
- }
181
- stats := strings .Fields (statsString )
182
- if len (stats ) < 3 {
183
- log .Printf ("Couldn't parse 3rd element from stats: '%s'" , statsString )
184
- return
186
+ type pidCallbackFn func (int ) bool
187
+
188
+ func walkProcessTree (pid int , fn pidCallbackFn ) error {
189
+ for {
190
+ stop := fn (pid )
191
+ if stop {
192
+ return nil
185
193
}
186
- ppid , err := strconv .Atoi (stats [3 ])
194
+
195
+ ppid , err := getProcesParentId (pid )
187
196
if err != nil {
188
- log .Printf ("ppid '%s' is not a number" , stats [3 ])
189
- return
197
+ return err
190
198
}
191
- if ppid == pid {
192
- return
199
+ if ppid == pid || ppid == 1 /* supervisor pid*/ {
200
+ return nil
193
201
}
194
202
pid = ppid
195
203
}
196
204
}
197
205
198
- func readProc (pid int , file string ) string {
206
+ func getProcesParentId (pid int ) (ppid int , err error ) {
207
+ statsString , err := readProc (pid , "stat" )
208
+ if err != nil {
209
+ return
210
+ }
211
+
212
+ stats := strings .Fields (statsString )
213
+ if len (stats ) < 3 {
214
+ err = fmt .Errorf ("CredentialHelper error cannot parse stats string: %s" , statsString )
215
+ return
216
+ }
217
+
218
+ parentId , err := strconv .Atoi (stats [3 ])
219
+ if err != nil {
220
+ err = fmt .Errorf ("CredentialHelper error cannot parse ppid: %s" , stats [3 ])
221
+ return
222
+ }
223
+
224
+ ppid = parentId
225
+ return
226
+ }
227
+
228
+ func readProc (pid int , file string ) (data string , err error ) {
199
229
procFile := fmt .Sprintf ("/proc/%d/%s" , pid , file )
200
230
// read file not using os.Stat
201
231
// see https://github.com/prometheus/procfs/blob/5162bec877a860b5ff140b5d13db31ebb0643dd3/internal/util/readfile.go#L27
202
232
const maxBufferSize = 1024 * 512
203
233
f , err := os .Open (procFile )
204
234
if err != nil {
205
- log . WithError ( err ). Printf ( "Error opening %s " , procFile )
206
- return ""
235
+ err = fmt . Errorf ( "CredentialHelper error opening proc file: %v " , err )
236
+ return
207
237
}
208
238
defer f .Close ()
209
239
reader := io .LimitReader (f , maxBufferSize )
210
240
buffer , err := ioutil .ReadAll (reader )
211
241
if err != nil {
212
- log . WithError ( err ). Printf ( "Error reading %s " , procFile )
213
- return ""
242
+ err = fmt . Errorf ( "CredentialHelper error reading proc file: %v " , err )
243
+ return
214
244
}
215
- return string (buffer )
245
+
246
+ data = string (buffer )
247
+ return
216
248
}
217
249
218
250
func init () {
0 commit comments