diff options
author | Ori Bernstein <ori@eigenstate.org> | 2021-09-03 02:47:18 +0000 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2021-09-03 02:47:18 +0000 |
commit | d9564c0642b9a8280f8e4dfe9ff15a2c65b6d93d (patch) | |
tree | 5c956042dbc6eea3d4ee776a74a50d6424c5d6e2 | |
parent | 485b334608910bbf6930a4f52ca946ba092fad04 (diff) |
git: separate author and committer
Git has the ability to track the person who
creates a commit separately from the person
who wrote the commit. For git9, we ignored
this feature.
However, as we start using git/import more,
it will be useful to figure out who imported
a commit, as well as who wrote it.
This change adds support for seeing this
information in git, as well as setting the
author and committer separately in git/import.
-rw-r--r-- | sys/lib/git/common.rc | 17 | ||||
-rw-r--r-- | sys/src/cmd/git/commit | 17 | ||||
-rw-r--r-- | sys/src/cmd/git/fs.c | 68 | ||||
-rwxr-xr-x | sys/src/cmd/git/import | 28 | ||||
-rw-r--r-- | sys/src/cmd/git/log.c | 3 | ||||
-rwxr-xr-x | sys/src/cmd/git/merge | 2 | ||||
-rw-r--r-- | sys/src/cmd/git/save.c | 65 |
7 files changed, 118 insertions, 82 deletions
diff --git a/sys/lib/git/common.rc b/sys/lib/git/common.rc index 787b5babd..653d6bfb1 100644 --- a/sys/lib/git/common.rc +++ b/sys/lib/git/common.rc @@ -38,7 +38,22 @@ fn present { status=() } -# merge1 out theirs base ours +fn whoami{ + name=`$nl{git/conf user.name} + email=`$nl{git/conf user.email} + if(test -f /adm/keys.who){ + if(~ $name '') + name=`$nl{awk -F'|' '$1=="'$user'" {x=$3} END{print x}' </adm/keys.who} + if(~ $email '') + email=`$nl{awk -F'|' '$1=="'$user'" {x=$5} END{print x}' </adm/keys.who} + } + if(~ $name '') + name=glenda + if(~ $email '') + email=glenda@9front.local +} + +# merge1 out ours base theirs fn merge1 {@{ rfork e n=$pid diff --git a/sys/src/cmd/git/commit b/sys/src/cmd/git/commit index 514c3a223..90f9cf26a 100644 --- a/sys/src/cmd/git/commit +++ b/sys/src/cmd/git/commit @@ -2,21 +2,6 @@ rfork ne . /sys/lib/git/common.rc -fn whoami{ - name=`{git/conf user.name} - email=`{git/conf user.email} - if(test -f /adm/keys.who){ - if(~ $name '') - name=`{awk -F'|' '$1=="'$user'" {x=$3} END{print x}' </adm/keys.who} - if(~ $email '') - email=`{awk -F'|' '$1=="'$user'" {x=$5} END{print x}' </adm/keys.who} - } - if(~ $name '') - name=glenda - if(~ $email '') - email=glenda@9front.local -} - fn findbranch{ branch=`{git/branch} if(test -e $gitfs/branch/$branch/tree){ @@ -92,7 +77,7 @@ fn commit{ msg=`''{cat $msgfile} if(! ~ $#parents 0) pflags='-p'^$parents - hash=`{git/save -n $"name -e $"email -m $"msg $pflags $files || die $status} + hash=`{git/save -n $"name -e $"email -m $"msg $pflags $files || die $status} rm -f .git/index9/merge-parents } diff --git a/sys/src/cmd/git/fs.c b/sys/src/cmd/git/fs.c index 945a720f2..6bed5521f 100644 --- a/sys/src/cmd/git/fs.c +++ b/sys/src/cmd/git/fs.c @@ -12,12 +12,13 @@ enum { Qhead, Qbranch, Qcommit, - Qcommitmsg, - Qcommitparent, - Qcommittree, - Qcommitdata, - Qcommithash, - Qcommitauthor, + Qmsg, + Qparent, + Qtree, + Qcdata, + Qhash, + Qauthor, + Qcommitter, Qobject, Qctl, Qmax, @@ -284,23 +285,23 @@ gcommitgen(int i, Dir *d, void *p) d->mode = 0755 | DMDIR; d->name = estrdup9p("tree"); d->qid.type = QTDIR; - d->qid.path = qpath(c, i, o->id, Qcommittree); + d->qid.path = qpath(c, i, o->id, Qtree); break; case 1: d->name = estrdup9p("parent"); - d->qid.path = qpath(c, i, o->id, Qcommitparent); + d->qid.path = qpath(c, i, o->id, Qparent); break; case 2: d->name = estrdup9p("msg"); - d->qid.path = qpath(c, i, o->id, Qcommitmsg); + d->qid.path = qpath(c, i, o->id, Qmsg); break; case 3: d->name = estrdup9p("hash"); - d->qid.path = qpath(c, i, o->id, Qcommithash); + d->qid.path = qpath(c, i, o->id, Qhash); break; case 4: d->name = estrdup9p("author"); - d->qid.path = qpath(c, i, o->id, Qcommitauthor); + d->qid.path = qpath(c, i, o->id, Qauthor); break; default: return -1; @@ -491,18 +492,20 @@ objwalk1(Qid *q, Object *o, Crumb *p, Crumb *c, char *name, vlong qdir, Gitaux * q->type = 0; c->mtime = o->commit->mtime; c->mode = 0644; - assert(qdir == Qcommit || qdir == Qobject || qdir == Qcommittree || qdir == Qhead); + assert(qdir == Qcommit || qdir == Qobject || qdir == Qtree || qdir == Qhead || qdir == Qcommitter); if(strcmp(name, "msg") == 0) - q->path = qpath(p, 0, o->id, Qcommitmsg); + q->path = qpath(p, 0, o->id, Qmsg); else if(strcmp(name, "parent") == 0) - q->path = qpath(p, 1, o->id, Qcommitparent); + q->path = qpath(p, 1, o->id, Qparent); else if(strcmp(name, "hash") == 0) - q->path = qpath(p, 2, o->id, Qcommithash); + q->path = qpath(p, 2, o->id, Qhash); else if(strcmp(name, "author") == 0) - q->path = qpath(p, 3, o->id, Qcommitauthor); + q->path = qpath(p, 3, o->id, Qauthor); + else if(strcmp(name, "committer") == 0) + q->path = qpath(p, 3, o->id, Qcommitter); else if(strcmp(name, "tree") == 0){ q->type = QTDIR; - q->path = qpath(p, 4, o->id, Qcommittree); + q->path = qpath(p, 4, o->id, Qtree); unref(c->obj); c->mode = DMDIR | 0755; c->obj = readobject(o->commit->tree); @@ -640,14 +643,15 @@ gitwalk1(Fid *fid, char *name, Qid *q) case Qcommit: e = objwalk1(q, o->obj, o, c, name, Qcommit, aux); break; - case Qcommittree: - e = objwalk1(q, o->obj, o, c, name, Qcommittree, aux); + case Qtree: + e = objwalk1(q, o->obj, o, c, name, Qtree, aux); break; - case Qcommitparent: - case Qcommitmsg: - case Qcommitdata: - case Qcommithash: - case Qcommitauthor: + case Qparent: + case Qmsg: + case Qcdata: + case Qhash: + case Qauthor: + case Qcommitter: case Qctl: return Enodir; default: @@ -760,20 +764,24 @@ gitread(Req *r) else dirread9p(r, objgen, aux); break; - case Qcommitmsg: + case Qmsg: readbuf(r, o->commit->msg, o->commit->nmsg); break; - case Qcommitparent: + case Qparent: readcommitparent(r, o); break; - case Qcommithash: + case Qhash: snprint(buf, sizeof(buf), "%H\n", o->hash); readstr(r, buf); break; - case Qcommitauthor: + case Qauthor: snprint(buf, sizeof(buf), "%s\n", o->commit->author); readstr(r, buf); break; + case Qcommitter: + snprint(buf, sizeof(buf), "%s\n", o->commit->committer); + readstr(r, buf); + break; case Qctl: e = readctl(r); break; @@ -785,8 +793,8 @@ gitread(Req *r) objread(r, aux); break; case Qcommit: - case Qcommittree: - case Qcommitdata: + case Qtree: + case Qcdata: objread(r, aux); break; default: diff --git a/sys/src/cmd/git/import b/sys/src/cmd/git/import index 1ce614a20..d8470dd01 100755 --- a/sys/src/cmd/git/import +++ b/sys/src/cmd/git/import @@ -7,11 +7,13 @@ fn sigexit { rm -f $diffpath } + fn apply @{ git/fs - email='' - name='' + amail='' + aname='' msg='' + whoami parents='-p'^`{git/query HEAD} branch=`{git/branch} if(test -e $gitfs/branch/$branch/tree) @@ -26,11 +28,11 @@ fn apply @{ } state=="headers" && /^From:/ { sub(/^From:[ \t]*/, "", $0); - name=$0; - email=$0; - sub(/[ \t]*<.*$/, "", name); - sub(/.*</, "", email); - sub(/>/, "", email); + aname=$0; + amail=$0; + sub(/[ \t]*<.*$/, "", aname); + sub(/^[^<]*</, "", amail); + sub(/>[^>]*$/, "", amail); } state=="headers" && /^Date:/{ sub(/^Date:[ \t]*/, "", $0) @@ -45,7 +47,7 @@ fn apply @{ state="body" next } - (state=="headers" || state=="body") && (/^diff / || /^--- /){ + (state=="headers" || state=="body") && (/^diff / || /^---( |$)/){ state="diff" } state=="body" { @@ -57,10 +59,10 @@ fn apply @{ END{ if(state != "diff") exit("malformed patch: " state); - if(name == "" || email == "" || date == "" || gotmsg == "") + if(aname == "" || amail == "" || date == "" || gotmsg == "") exit("missing headers"); - printf "%s", name > "/env/name" - printf "%s", email > "/env/email" + printf "%s", aname > "/env/aname" + printf "%s", amail > "/env/amail" printf "%s", date > "/env/date" } ' || die 'could not import:' $status @@ -79,8 +81,8 @@ fn apply @{ } git/walk -fRMA $files if(~ $#nocommit 0){ - hash=`{git/save -n $name -e $email -m $msg -d $date $parents $files} - echo $hash > $refpath + if(hash=`{git/save -n $aname -e $amail -N $name -E $email -m $msg -d $date $parents $files}) + echo $hash > $refpath } status='''' ' diff --git a/sys/src/cmd/git/log.c b/sys/src/cmd/git/log.c index 2a0692aba..af9b90504 100644 --- a/sys/src/cmd/git/log.c +++ b/sys/src/cmd/git/log.c @@ -153,6 +153,9 @@ show(Object *o) tmtime(&tm, o->commit->mtime, tzload("local")); Bprint(out, "Hash:\t%H\n", o->hash); Bprint(out, "Author:\t%s\n", o->commit->author); + if(o->commit->committer != nil + && strcmp(o->commit->author, o->commit->committer) != 0) + Bprint(out, "Commiter:\t%s\n", o->commit->committer); Bprint(out, "Date:\t%τ\n", tmfmt(&tm, "WW MMM D hh:mm:ss z YYYY")); Bprint(out, "\n"); p = o->commit->msg; diff --git a/sys/src/cmd/git/merge b/sys/src/cmd/git/merge index 3d7a97a74..051e22483 100755 --- a/sys/src/cmd/git/merge +++ b/sys/src/cmd/git/merge @@ -12,7 +12,7 @@ fn merge{ ours=$ourbr/$f base=$basebr/$f theirs=$theirbr/$f - merge1 ./$f $theirs $base $ours + merge1 ./$f $ours $base $theirs } } diff --git a/sys/src/cmd/git/save.c b/sys/src/cmd/git/save.c index d6062769c..08a1a50cf 100644 --- a/sys/src/cmd/git/save.c +++ b/sys/src/cmd/git/save.c @@ -14,6 +14,14 @@ enum { Maxparents = 16, }; +char *authorname; +char *authoremail; +char *committername; +char *committeremail; +char *commitmsg; +Hash parents[Maxparents]; +int nparents; + int gitmode(Dirent *e) { @@ -299,7 +307,7 @@ err: void -mkcommit(Hash *c, char *msg, char *name, char *email, vlong date, Hash *parents, int nparents, Hash tree) +mkcommit(Hash *c, vlong date, Hash tree) { char *s, h[64]; int ns, nh, i; @@ -309,10 +317,10 @@ mkcommit(Hash *c, char *msg, char *name, char *email, vlong date, Hash *parents, fmtprint(&f, "tree %H\n", tree); for(i = 0; i < nparents; i++) fmtprint(&f, "parent %H\n", parents[i]); - fmtprint(&f, "author %s <%s> %lld +0000\n", name, email, date); - fmtprint(&f, "committer %s <%s> %lld +0000\n", name, email, date); + fmtprint(&f, "author %s <%s> %lld +0000\n", authorname, authoremail, date); + fmtprint(&f, "committer %s <%s> %lld +0000\n", committername, committeremail, date); fmtprint(&f, "\n"); - fmtprint(&f, "%s", msg); + fmtprint(&f, "%s", commitmsg); s = fmtstrflush(&f); ns = strlen(s); @@ -346,9 +354,9 @@ usage(void) void main(int argc, char **argv) { - Hash th, ch, parents[Maxparents]; - char *msg, *name, *email, *dstr, cwd[1024]; - int i, r, ncwd, nparents; + Hash th, ch; + char *dstr, cwd[1024]; + int i, r, ncwd; vlong date; Object *t; @@ -357,19 +365,29 @@ main(int argc, char **argv) sysfatal("could not find git repo: %r"); if(getwd(cwd, sizeof(cwd)) == nil) sysfatal("getcwd: %r"); - msg = nil; - name = nil; - email = nil; dstr = nil; date = time(nil); - nparents = 0; ncwd = strlen(cwd); ARGBEGIN{ - case 'm': msg = EARGF(usage()); break; - case 'n': name = EARGF(usage()); break; - case 'e': email = EARGF(usage()); break; - case 'd': dstr = EARGF(usage()); break; + case 'm': + commitmsg = EARGF(usage()); + break; + case 'n': + authorname = EARGF(usage()); + break; + case 'e': + authoremail = EARGF(usage()); + break; + case 'N': + committername = EARGF(usage()); + break; + case 'E': + committeremail = EARGF(usage()); + break; + case 'd': + dstr = EARGF(usage()); + break; case 'p': if(nparents >= Maxparents) sysfatal("too many parents"); @@ -378,21 +396,26 @@ main(int argc, char **argv) break; default: usage(); + break; }ARGEND; - if(!msg) + if(commitmsg == nil) sysfatal("missing message"); - if(!name) + if(authorname == nil) sysfatal("missing name"); - if(!email) + if(authoremail == nil) sysfatal("missing email"); + if((committername == nil) != (committeremail == nil)) + sysfatal("partially specified committer"); + if(committername == nil && committeremail == nil){ + committername = authorname; + committeremail = authoremail; + } if(dstr){ date=strtoll(dstr, &dstr, 10); if(strlen(dstr) != 0) sysfatal("could not parse date %s", dstr); } - if(msg == nil || name == nil) - usage(); for(i = 0; i < argc; i++){ cleanname(argv[i]); if(*argv[i] == '/' && strncmp(argv[i], cwd, ncwd) == 0) @@ -405,7 +428,7 @@ main(int argc, char **argv) r = treeify(t, argv, argv + argc, 0, &th); if(r == -1) sysfatal("could not commit: %r\n"); - mkcommit(&ch, msg, name, email, date, parents, nparents, th); + mkcommit(&ch, date, th); print("%H\n", ch); exits(nil); } |