summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2021-09-03 02:47:18 +0000
committerOri Bernstein <ori@eigenstate.org>2021-09-03 02:47:18 +0000
commitd9564c0642b9a8280f8e4dfe9ff15a2c65b6d93d (patch)
tree5c956042dbc6eea3d4ee776a74a50d6424c5d6e2
parent485b334608910bbf6930a4f52ca946ba092fad04 (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.rc17
-rw-r--r--sys/src/cmd/git/commit17
-rw-r--r--sys/src/cmd/git/fs.c68
-rwxr-xr-xsys/src/cmd/git/import28
-rw-r--r--sys/src/cmd/git/log.c3
-rwxr-xr-xsys/src/cmd/git/merge2
-rw-r--r--sys/src/cmd/git/save.c65
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);
}