[mike@mwxm4]
This commit is contained in:
+47
-17
@@ -20,8 +20,11 @@ var (
|
||||
// literally named "git".
|
||||
lsEntryRe = regexp.MustCompile(`^\S+\s+\d+\s+\S+\s+\S+\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)$`)
|
||||
gitDirRe = regexp.MustCompile(`^(.*)\.git$`)
|
||||
sanRe = regexp.MustCompile(`[,;:\\/='"|?><-]+`)
|
||||
wsRe = regexp.MustCompile(`\s+`)
|
||||
// '!' is in here for the server's sake: csh expands history even inside
|
||||
// single quotes, so a comment like "fix!now" would reach it as something
|
||||
// else entirely (see remoteRejected).
|
||||
sanRe = regexp.MustCompile(`[!,;:\\/='"|?><-]+`)
|
||||
wsRe = regexp.MustCompile(`\s+`)
|
||||
)
|
||||
|
||||
// listMarker separates the two sections of the combined listing command, so
|
||||
@@ -58,7 +61,13 @@ func parseDuSizes(lines []string) map[string]int64 {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
out[strings.TrimPrefix(strings.TrimSpace(m[2]), "./")] = kb * 1024
|
||||
// du echoes the path it was given, and find gives it an absolute one:
|
||||
// key on the last element, which is what the listing calls the entry
|
||||
name := strings.TrimSpace(m[2])
|
||||
if i := strings.LastIndexByte(name, '/'); i >= 0 {
|
||||
name = name[i+1:]
|
||||
}
|
||||
out[name] = kb * 1024
|
||||
}
|
||||
return out
|
||||
}
|
||||
@@ -251,14 +260,22 @@ func runCommandDepth(line string, depth int) bool {
|
||||
one, many = "archive", "archives"
|
||||
}
|
||||
pat := strings.ToLower(word(words, 1))
|
||||
remote := "/bin/ls -ltr " + shq(path)
|
||||
remote := "/bin/ls -ltr " + shq(serverPath(path))
|
||||
if !opt["a"] {
|
||||
// archives are files and carry a real size; repositories are
|
||||
// directories, whose listed size is the inode's, so ask du in the
|
||||
// same round trip. Nothing shell-specific here on purpose: the
|
||||
// login shell may be csh, where "2>/dev/null" is not a redirection
|
||||
// but an argument followed by one.
|
||||
remote += "; echo " + shq(listMarker) + "; du -sk *.git"
|
||||
//
|
||||
// The pattern goes to find, quoted, and never to the shell. A glob
|
||||
// that matches nothing is a fatal error in a non-interactive zsh —
|
||||
// "no matches found: *.git" — which aborts the command and turned an
|
||||
// empty server into "could not list". sh would have handed the
|
||||
// literal "*.git" to du instead, which is not much better.
|
||||
remote += "; echo " + shq(listMarker) +
|
||||
"; find " + shq(serverPath(path)) + " -maxdepth 1 -name " +
|
||||
shq("*"+suffix) + " -exec du -sk {} +"
|
||||
}
|
||||
lines, err := sshOut(remote)
|
||||
lsLines, duLines := splitAtMarker(lines, listMarker)
|
||||
@@ -284,7 +301,13 @@ func runCommandDepth(line string, depth int) bool {
|
||||
// complain when nothing usable came back at all.
|
||||
if len(entries) == 0 {
|
||||
if err != nil {
|
||||
errorln("could not list " + many + " on the git server")
|
||||
what := "could not list " + many + " on the git server"
|
||||
if opt["a"] {
|
||||
// by far the likeliest reason, and one the wording used to
|
||||
// hide behind something that sounded like a dead connection
|
||||
what += " — is there an 'archive' directory in " + cfg.GitPath + "?"
|
||||
}
|
||||
errorln(what)
|
||||
break
|
||||
}
|
||||
what := "no " + many + " on the git server"
|
||||
@@ -325,8 +348,8 @@ func runCommandDepth(line string, depth int) bool {
|
||||
errorln("repository not found")
|
||||
break
|
||||
}
|
||||
logLines, _ := sshOut("cd " + shq(cfg.GitPath+"/"+prj+".git") +
|
||||
" && git log --reverse --format='%h %ct %s'")
|
||||
logLines, _ := sshOut("git --git-dir=" + shq(serverPath(prj+".git")) +
|
||||
" log --reverse --format='%h %ct %s'")
|
||||
repolog(logLines)
|
||||
|
||||
case "log":
|
||||
@@ -392,7 +415,7 @@ func runCommandDepth(line string, depth int) bool {
|
||||
if !gitOK(DIR, "push") {
|
||||
break
|
||||
}
|
||||
sshOK("touch " + shq(cfg.GitPath+"/"+PRJ+".git"))
|
||||
sshOK("touch " + shq(serverPath(PRJ+".git")))
|
||||
if targets, _ := cfg.mirrorTargets(); truthy(cfg.Mirror) && len(activeRemotes(targets)) > 0 {
|
||||
handlePushRemote("") // auto-mirror to every active server
|
||||
}
|
||||
@@ -442,13 +465,17 @@ func runCommandDepth(line string, depth int) bool {
|
||||
if comment != "" {
|
||||
name = PRJ + "_" + z + "_" + comment
|
||||
}
|
||||
if !sshOK("cp -r " + shq(PRJ+".git") + " " + shq("archive/"+name+".git")) {
|
||||
// the archive directory is mgsh's own convention, so make it rather than
|
||||
// fail on a server where nobody has created it yet
|
||||
if !sshOK("mkdir -p " + shq(serverPath("archive")) +
|
||||
" && cp -r " + shq(serverPath(PRJ+".git")) + " " + shq(serverPath("archive/"+name+".git"))) {
|
||||
break
|
||||
}
|
||||
if !sshOK("cd archive && tar cvzf " + shq(name+".git.tar.gz") + " " + shq(name+".git")) {
|
||||
if !sshOK("tar cvzf " + shq(serverPath("archive/"+name+".git.tar.gz")) +
|
||||
" -C " + shq(serverPath("archive")) + " " + shq(name+".git")) {
|
||||
break
|
||||
}
|
||||
sshOK("rm -rf " + shq("archive/"+name+".git"))
|
||||
sshOK("rm -rf " + shq(serverPath("archive/"+name+".git")))
|
||||
|
||||
case "init": // create a new repository from the current directory
|
||||
if !requireProject() {
|
||||
@@ -468,11 +495,13 @@ func runCommandDepth(line string, depth int) bool {
|
||||
if exists && !yesno("overwrite existing repository "+PRJ+" on the server?", false) {
|
||||
break
|
||||
}
|
||||
remote := shq(cfg.GitPath + "/" + PRJ + ".git")
|
||||
remote := shq(serverPath(PRJ + ".git"))
|
||||
if !sshOK("rm -rf " + remote) {
|
||||
break
|
||||
}
|
||||
if !sshOK("mkdir " + remote + " && cd " + remote + " && git --bare init") {
|
||||
// `git init --bare <path>` makes the directory itself: one command, and
|
||||
// none of it depends on a `cd` having worked
|
||||
if !sshOK("git init --bare " + remote) {
|
||||
break
|
||||
}
|
||||
gi := DIR + "/.gitignore"
|
||||
@@ -555,13 +584,14 @@ func runCommandDepth(line string, depth int) bool {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if !sshOK("cd archive && tar xvzf " + shq(prj+".git.tar.gz")) {
|
||||
if !sshOK("tar xvzf " + shq(serverPath("archive/"+prj+".git.tar.gz")) +
|
||||
" -C " + shq(serverPath("archive"))) {
|
||||
break
|
||||
}
|
||||
if !gitOK(BASE, "clone", URL+"/archive/"+prj+".git") {
|
||||
break
|
||||
}
|
||||
sshOK("rm -rf " + shq("archive/"+prj+".git"))
|
||||
sshOK("rm -rf " + shq(serverPath("archive/"+prj+".git")))
|
||||
}
|
||||
if isDir(BASE + "/" + prj) {
|
||||
PRJ = prj
|
||||
@@ -572,7 +602,7 @@ func runCommandDepth(line string, depth int) bool {
|
||||
if opt["a"] {
|
||||
path = "./archive"
|
||||
}
|
||||
lines, err := sshOut("/bin/ls " + shq(path))
|
||||
lines, err := sshOut("/bin/ls " + shq(serverPath(path)))
|
||||
if err != nil {
|
||||
errorln("could not list repositories on the git server")
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user