diff --git a/.gitignore b/.gitignore index ae8348cb..8957273c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,27 +1,23 @@ -(^|/)CVS($|/) -(^|/)\.hg($|/) -(^|/)\.hgtags($|/) -^plan9.log$ -^plan9-reverse.log$ -^state$ -^state.old$ -^state.journal$ -\.o$ -\.a$ -^man/man[0-9]+/.*\.html$ -^src/.*/o\.[^/]+$ -y.tab.[ch]$ -^src/cmd/rc/x.tab.h$ -^unix/.*\.tgz$ -^bin/ -^log/ -^dict/ -^postscript/font/ -\.orig$ +plan9.log +plan9-reverse.log +state +state.old +state.journal +*.o +*.a +man/man?/*.html +src/**/o.* +y.tab.[ch] +src/cmd/rc/x.tab.h +unix/*.tgz +bin/ +log/ +dict/ +postscript/font/ +*.orig config install.log install.sum last-change -lib/codereview/codereview.pyc src/cmd/awk/y.output src/cmd/devdraw/latin1.h diff --git a/bin/codereview b/bin/codereview index 5339d566..307091a7 100755 --- a/bin/codereview +++ b/bin/codereview @@ -1,2 +1,142 @@ -#!/bin/sh -$PLAN9/bin/codereview.py -r rsc --cc codebot --send_mail "$@" +#!/usr/local/plan9/bin/rc + +git=git +show=false +fn gitshow { + echo '%' git $* + git $* +} +if(! ~ $#* 0 && ~ $1 -v) { + git=gitshow + show=true + shift +} + +if(~ $#* 0) { + echo 'usage: codereview ' >[1=2] + exit usage +} + +if(~ $#PLAN9 0) { + PLAN9=/usr/local/plan9 +} +if(! test -d $PLAN9/lib/git) { + echo 'codereview: cannot find $PLAN9/lib/git' >[1=2] + exit git +} + +if(! test -e $PLAN9/.git/hooks/commit-msg) { + if($show) { + echo '% ln -s ../../lib/git/commit-msg.hook $PLAN9/.git/hooks/commit-msg' + } + ln -s ../../lib/git/commit-msg.hook $PLAN9/.git/hooks/commit-msg +} + +switch($1) { +case help + 9 man 1 codereview + +case pending + shift + if(! ~ $#* 0) { + echo 'usage: codereview pending' >[1=2] + exit usage + } + $git branch --list + +case create + shift + if(! ~ $#* 1) { + echo 'usage: codereview create branchname' >[1=2] + exit usage + } + branch=$1 + if(! git branch -l | 9 grep '\* master$') { + echo 'codereview: create not on master branch; use codereview commit' >[1=2] + exit master + } + if($show) { + echo '% git branch '$branch' && git commit || git branch -d '$branch >[1=2] + } + git branch $branch && git commit $* || git branch -d $branch + +case commit + shift + if(git branch -l | 9 grep '\* master$') { + echo 'codereview: commit on master branch; use codereview create ' >[1=2] + exit master + } + if(~ `{git merge-base HEAD HEAD} `{git merge-base HEAD master}) { + # first commit on branch, somehow. + $git commit $* + exit $status + } + $git commit --amend $* + exit $status + +case upload + if(git branch -l | 9 grep '\* master$') { + echo 'codereview: upload on master branch' >[1=2] + exit master + } + if(~ `{git merge-base HEAD HEAD} `{git merge-base HEAD master}) { + # no commit on branch + echo 'codereview: no commits yet on this feature branch' >[1=2] + exit commit + } + if(! 9 grep 'machine plan9port-review.googlesource.com' $HOME/.netrc >/dev/null >[2=1]) { + echo 'codereview: warning: cannot find plan9port-review in netrc' >[1=2] + } + $git push https://plan9port-review.googlesource.com/plan9 HEAD:refs/for/master >[2=1] | 9 sed 's/.* //' + +case sync + shift + if(! ~ $#* 0) { + echo 'usage: codereview sync' >[1=2] + exit usage + } + $git fetch -q + + branch=`{git branch -l | 9 sed -n 's/^\* //p'} + if(~ $branch master) { + $git merge -q --ff-only origin/master + exit $status + } + + if(~ `{git merge-base HEAD HEAD} `{git merge-base HEAD master}) { + # no commit on branch + git merge -q --ff-only origin/master + exit $status + } + + # Exactly this commit in master. Fast-forward from master and delete this branch. + if(git branch -r --contains HEAD | 9 grep '^ *origin/master$') { + $git checkout -q master + $git merge -q --ff-only origin/master + $git branch -q -d $branch + exit $status + } + + changeid=`{git log -n 1 | 9 sed -n 's/^ Change-Id: //p'} + if(~ $#changeid 0) { + echo 'codereview: cannot find change id' + exit changeid + } + + if(git log --grep 'Change-Id: '$changeid origin/master | 9 grep .) { + # Something like this got submitted. + $git checkout -q master + $git merge -q --ff-only origin/master + echo 'Change submitted but perhaps not identical to your copy.' >[1=2] + echo 'To remove old copy:' git branch -d $branch >[1=2] + exit 1 + } + + if(git branch -r --contains master | 9 grep '^ *origin/master$') + $git branch -f master origin/master + $git rebase -q origin/master + +case * + echo 'codereview: unrecognized command '$1 >[1=2] + exit usage +} diff --git a/lib/git/commit-msg.hook b/lib/git/commit-msg.hook new file mode 100755 index 00000000..985016b5 --- /dev/null +++ b/lib/git/commit-msg.hook @@ -0,0 +1,104 @@ +#!/bin/sh +# From Gerrit Code Review 2.2.1 +# +# Part of Gerrit Code Review (http://code.google.com/p/gerrit/) +# +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +CHANGE_ID_AFTER="Bug|Issue" +MSG="$1" + +# Check for, and add if missing, a unique Change-Id +# +add_ChangeId() { + clean_message=`sed -e ' + /^diff --git a\/.*/{ + s/// + q + } + /^Signed-off-by:/d + /^#/d + ' "$MSG" | git stripspace` + if test -z "$clean_message" + then + return + fi + + if grep -i '^Change-Id:' "$MSG" >/dev/null + then + return + fi + + id=`_gen_ChangeId` + perl -e ' + $MSG = shift; + $id = shift; + $CHANGE_ID_AFTER = shift; + + undef $/; + open(I, $MSG); $_ = ; close I; + s|^diff --git a/.*||ms; + s|^#.*$||mg; + exit unless $_; + + @message = split /\n/; + $haveFooter = 0; + $startFooter = @message; + for($line = @message - 1; $line >= 0; $line--) { + $_ = $message[$line]; + + if (/^[a-zA-Z0-9-]+:/ && !m,^[a-z0-9-]+://,) { + $haveFooter++; + next; + } + next if /^[ []/; + $startFooter = $line if ($haveFooter && /^\r?$/); + last; + } + + @footer = @message[$startFooter+1..@message]; + @message = @message[0..$startFooter]; + push(@footer, "") unless @footer; + + for ($line = 0; $line < @footer; $line++) { + $_ = $footer[$line]; + next if /^($CHANGE_ID_AFTER):/i; + last; + } + splice(@footer, $line, 0, "Change-Id: I$id"); + + $_ = join("\n", @message, @footer); + open(O, ">$MSG"); print O; close O; + ' "$MSG" "$id" "$CHANGE_ID_AFTER" +} +_gen_ChangeIdInput() { + echo "tree `git write-tree`" + if parent=`git rev-parse HEAD^0 2>/dev/null` + then + echo "parent $parent" + fi + echo "author `git var GIT_AUTHOR_IDENT`" + echo "committer `git var GIT_COMMITTER_IDENT`" + echo + printf '%s' "$clean_message" +} +_gen_ChangeId() { + _gen_ChangeIdInput | + git hash-object -t commit --stdin +} + + +add_ChangeId diff --git a/man/man1/codereview.1 b/man/man1/codereview.1 index 86d07b29..0b713c45 100644 --- a/man/man1/codereview.1 +++ b/man/man1/codereview.1 @@ -2,70 +2,154 @@ .SH NAME codereview \- review of submitted changes (experimental) .SH SYNOPSIS -.B hg +.B git .B diff +.B HEAD .I path ... .PP .B codereview -.I path ... +[ +.B -v +] +.B create +.I name +[ +.B -a +] .PP .B codereview -.B -i -.I issue -.I path ... +[ +.B -v +] +.B commit +[ +.B -a +] +.PP +.B codereview +[ +.B -v +] +.B upload +.PP +.B codereview +[ +.B -v +] +.B pending +.PP +.B codereview +[ +.B -v +] +.B sync .SH DESCRIPTION .I Codereview -uploads suggested changes to the code review server -.I codereview.appspot.com -and sends email to reviewers. +manages the review and submission of changes to the Plan 9 from User Space project. It must be used from within a Plan 9 from User Space tree -checked out via Mercurial +checked out via Git (see -.IR hg (1)). +.IR git (1)). .PP -A developer makes changes to a local copy of the tree -and reviews them locally using -.I hg -.I diff . -When the changes are ready for external review, the -developer creates a review issue by running +A developer makes changes to a local copy of the tree, +reviews them by using +.I git +.I diff +.IR HEAD +and then commits them to a ``feature branch'' +using .I codereview -naming the files to be reviewed. -.I Codereview -prompts for a Google Accounts user name -and password to log in to -.I http://codereview.appspot.com/ -and create a new review issue. -Once created, it prints a line like -.EX -Issue created. URL: http://codereview.appspot.com/96161 -.EE -among other output. -.PP -The reviewer will likely respond with comments -and suggestions for improving the submission. -After making the changes, reupload by repeating -the +.IR create . +.I Git +requires that changes be added to a ``staging area'' before the initial commit, +using commands such as +.I git +.I add +and +.I git +.IR rm . +The +.B -a +option causes .I codereview -command with the -.B -i -option to specify the issue number -(in the above example, 96161). +.I create +to add all local modifications to the staging area as part of the initial commit. +.PP +Once a feature branch is created, files can still be edited, but they must then be +incorporated into the change by using +.I codereview +.IR commit . +.PP +If other changes have been committed since the feature branch was created, +.I codereview +.I sync +will update it to be based on the most recent copy of the repository. +.PP +When the code is ready for review, +.I codereview +.I upload +uploads the change to +.HR https://plan9port-review.googlesource.com/ +for review. +In order to upload, +.I git +must have access to a +.I $HOME/.netrc +that contains a password obtained from +.HR https://plan9port-review.googlesource.com/#/settings/http-password . +.PP +The most likely initial result of a code review is suggestions for +improving the code. +After making those changes, repeat the +.I codereview +.I commit +and +.I codereview +.I upload +steps. +.PP +Once the code is ready, it will be submitted by the reviewer using the web interface. +At that point, +.I codereview +.I sync .PP -Once the reviewer accepts the changes, they will be applied -automatically using the patch uploaded to the review server. -To update the local tree, run -.I hg -.I pull -with the -.B -u -option. -.SH SEE ALSO -.HR http://codereview.appspot.com/ -.SH BUGS The .I codereview -command should be replaced by a proper Mercurial extension. +.I pending +command lists the active feature branches. .PP -Making changes to the repository via patches -discards the executable bit on new shell scripts. +All the +.I codereview +commands take a leading +.B -v +option, which causes them to print +.I git +commands being executed. +This can be useful for debugging +.IR codereview . +.PP +The +.I codereview +command depends on a +.I git +``commit hook'' +script being in place to add +.L Change-Id +lines to the commit messages. +.I Codereview +installs the hook at startup, if necessary, +by adding a symbolic link from +.B $PLAN9/.git/hooks/commit-msg +to +.BR $PLAN9/lib/git/commit-msg.hook . +.SH SEE ALSO +.IR git (1), +.HR http://plan9port-review.googlesource.com/ +.SH BUGS +.I Git +is too complicated to use. +The +.I codereview +script helps, but a working understanding of +.I git +is still required. diff --git a/man/man1/hg.1 b/man/man1/git.1 similarity index 53% rename from man/man1/hg.1 rename to man/man1/git.1 index b46dfc1b..2cedace7 100644 --- a/man/man1/hg.1 +++ b/man/man1/git.1 @@ -1,42 +1,34 @@ .TH HG 1 .SH NAME -hg, cvs \- introduction to using plan9port Mercurial repository +git, hg, cvs \- introduction to using plan9port Git repository .SH SYNOPSIS -.B hg +.B git .B clone .B http://code.swtch.com/plan9port .B plan9 .PP -.B hg +.B git .B pull -.B -u .PP -.B hg +.B git .B diff -[ -.B -r .I revision -] [ .I path ... ] .PP -.B hg -.B serve -.PP -.B hg -.B view +.B gitk .PP .B web .B http://code.swtch.com/plan9port .SH DESCRIPTION The master source tree for Plan 9 from User Space is maintained -using the source control system Mercurial +using the source control system Git as a substitute for Plan 9's \fIreplica\fR(8) and dump file system. .PP The first argument to -.I hg +.I git is a command, which determines the form of the rest of the command line. .PP The @@ -45,67 +37,53 @@ command downloads a copy of the tree into the directory .BR plan9 , which it will create. After -.B hg +.B git .BR clone , the other commands listed should be run within the .B plan9 directory tree. .PP -Unlike CVS, Mercurial downloads the entire revision history +Git downloads the entire revision history of Plan 9 from User Space in addition to the current tree. .PP -.I Hg +.I Git .I pull incorporates changes from the master repository -into the local revision history. -The -.B -u -flag applies these changes to the current file tree. +into the local revision history and applies them to the +current file tree. .PP -.I Hg +.I Git .I diff runs Unix's .IR diff (1) to compare the files in the local tree with the corresponding files in the revision history. -By default it compares against the version that was most recently -incorporated into the local tree. -The -.B -r -flag specifies an alternate version to compare against. The special revision -.B tip -refers to the most recent version on the server. +.B HEAD +refers to the most recent version in the version history. .PP -.I Hg -.I serve -starts an HTTP server serving information about -the local repository at the address -.BR http://localhost:8000/ . -.PP -.I Hg -.I view +.I Gitk starts an interactive history viewer. .PP -The Mercurial tree can be inspected on the web at +The Git tree can be inspected on the web at .HR http://code.swtch.com/plan9port/ "" . .SH FILES .TP -.B \*9/.hg +.B \*9/.git directory containing Mercurial local repository .TP -.B .hgignore -list of files and wildcards to exclude from Mercurial operations +.B .gitignore +list of files and wildcards to exclude from Git operations .SH SEE ALSO .IR codereview (1) .PP Unix's -\fIhg\fR(1), -.HR http://www.selenic.com/mercurial/wiki/ +\fIgit\fR(1), +.HR http://git-scm.com/doc .PP .HR http://code.swtch.com/plan9port/ .SH BUGS -Plan 9 from User Space is no longer accessible using CVS; -you must use Mercurial. +Plan 9 from User Space is no longer accessible using CVS or Mercurial; +you must use Git.