Skip to content

Commit 6b128f8

Browse files
cmd: refactor runServ()
Coalesce access mode detection into one place. Yes, "upload" really has opposite semantics for git commands vs. git-lfs commands. Wow. This commit makes no functional changes.
1 parent 08ab232 commit 6b128f8

File tree

1 file changed

+50
-34
lines changed

1 file changed

+50
-34
lines changed

cmd/serv.go

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ import (
3636
)
3737

3838
const (
39-
lfsAuthenticateVerb = "git-lfs-authenticate"
39+
verbUploadPack = "git-upload-pack"
40+
verbUploadArchive = "git-upload-archive"
41+
verbReceivePack = "git-receive-pack"
42+
verbLfsAuthenticate = "git-lfs-authenticate"
4043
)
4144

4245
// CmdServ represents the available serv sub-command.
@@ -73,11 +76,16 @@ func setup(ctx context.Context, debug bool) {
7376
}
7477

7578
var (
76-
allowedCommands = map[string]perm.AccessMode{
77-
"git-upload-pack": perm.AccessModeRead,
78-
"git-upload-archive": perm.AccessModeRead,
79-
"git-receive-pack": perm.AccessModeWrite,
80-
lfsAuthenticateVerb: perm.AccessModeNone,
79+
// anything not in map will return false (zero value)
80+
// keep getAccessMode() in sync
81+
allowedCommands = map[string]bool{
82+
verbUploadPack: true,
83+
verbUploadArchive: true,
84+
verbReceivePack: true,
85+
verbLfsAuthenticate: true,
86+
}
87+
allowedCommandsLfs = map[string]bool{
88+
verbLfsAuthenticate: true,
8189
}
8290
alphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
8391
)
@@ -124,6 +132,24 @@ func handleCliResponseExtra(extra private.ResponseExtra) error {
124132
return nil
125133
}
126134

135+
func getAccessMode(verb string, lfsVerb string) perm.AccessMode {
136+
switch verb {
137+
case verbUploadPack, verbUploadArchive:
138+
return perm.AccessModeRead
139+
case verbReceivePack:
140+
return perm.AccessModeWrite
141+
case verbLfsAuthenticate:
142+
switch lfsVerb {
143+
case "upload":
144+
return perm.AccessModeWrite
145+
case "download":
146+
return perm.AccessModeRead
147+
}
148+
}
149+
// should be unreachable
150+
return perm.AccessModeNone
151+
}
152+
127153
func runServ(c *cli.Context) error {
128154
ctx, cancel := installSignals()
129155
defer cancel()
@@ -193,17 +219,7 @@ func runServ(c *cli.Context) error {
193219
if repoPath[0] == '/' {
194220
repoPath = repoPath[1:]
195221
}
196-
197222
var lfsVerb string
198-
if verb == lfsAuthenticateVerb {
199-
if !setting.LFS.StartServer {
200-
return fail(ctx, "Unknown git command", "LFS authentication request over SSH denied, LFS support is disabled")
201-
}
202-
203-
if len(words) > 2 {
204-
lfsVerb = words[2]
205-
}
206-
}
207223

208224
rr := strings.SplitN(repoPath, "/", 2)
209225
if len(rr) != 2 {
@@ -240,28 +256,28 @@ func runServ(c *cli.Context) error {
240256
}()
241257
}
242258

243-
requestedMode, has := allowedCommands[verb]
244-
if !has {
259+
if allowedCommands[verb] {
260+
if allowedCommandsLfs[verb] {
261+
if !setting.LFS.StartServer {
262+
return fail(ctx, "Unknown git command", "LFS authentication request over SSH denied, LFS support is disabled")
263+
}
264+
if len(words) > 2 {
265+
lfsVerb = words[2]
266+
}
267+
}
268+
} else {
245269
return fail(ctx, "Unknown git command", "Unknown git command %s", verb)
246270
}
247271

248-
if verb == lfsAuthenticateVerb {
249-
if lfsVerb == "upload" {
250-
requestedMode = perm.AccessModeWrite
251-
} else if lfsVerb == "download" {
252-
requestedMode = perm.AccessModeRead
253-
} else {
254-
return fail(ctx, "Unknown LFS verb", "Unknown lfs verb %s", lfsVerb)
255-
}
256-
}
272+
requestedMode := getAccessMode(verb, lfsVerb)
257273

258274
results, extra := private.ServCommand(ctx, keyID, username, reponame, requestedMode, verb, lfsVerb)
259275
if extra.HasError() {
260276
return fail(ctx, extra.UserMsg, "ServCommand failed: %s", extra.Error)
261277
}
262278

263279
// LFS token authentication
264-
if verb == lfsAuthenticateVerb {
280+
if verb == verbLfsAuthenticate {
265281
url := fmt.Sprintf("%s%s/%s.git/info/lfs", setting.AppURL, url.PathEscape(results.OwnerName), url.PathEscape(results.RepoName))
266282

267283
now := time.Now()
@@ -296,22 +312,22 @@ func runServ(c *cli.Context) error {
296312
return nil
297313
}
298314

299-
var gitcmd *exec.Cmd
300315
gitBinPath := filepath.Dir(git.GitExecutable) // e.g. /usr/bin
301316
gitBinVerb := filepath.Join(gitBinPath, verb) // e.g. /usr/bin/git-upload-pack
317+
gitExe := gitBinVerb
318+
gitArgs := make([]string, 0, 3) // capacity to accommodate max args
302319
if _, err := os.Stat(gitBinVerb); err != nil {
303320
// if the command "git-upload-pack" doesn't exist, try to split "git-upload-pack" to use the sub-command with git
304321
// ps: Windows only has "git.exe" in the bin path, so Windows always uses this way
305322
verbFields := strings.SplitN(verb, "-", 2)
306323
if len(verbFields) == 2 {
307324
// use git binary with the sub-command part: "C:\...\bin\git.exe", "upload-pack", ...
308-
gitcmd = exec.CommandContext(ctx, git.GitExecutable, verbFields[1], repoPath)
325+
gitExe = git.GitExecutable
326+
gitArgs = append(gitArgs, verbFields[1])
309327
}
310328
}
311-
if gitcmd == nil {
312-
// by default, use the verb (it has been checked above by allowedCommands)
313-
gitcmd = exec.CommandContext(ctx, gitBinVerb, repoPath)
314-
}
329+
gitArgs = append(gitArgs, repoPath)
330+
gitcmd := exec.CommandContext(ctx, gitExe, gitArgs...)
315331

316332
process.SetSysProcAttribute(gitcmd)
317333
gitcmd.Dir = setting.RepoRootPath

0 commit comments

Comments
 (0)