'hub' ADC doc and rudimentary test script
This commit is contained in:
parent
49e64a4f11
commit
6d3c2fbcef
182
contrib/adc/hub.mkd
Normal file
182
contrib/adc/hub.mkd
Normal file
|
@ -0,0 +1,182 @@
|
|||
# the 'hub' ADC
|
||||
|
||||
In this document:
|
||||
|
||||
* <a href="#_a_home_grown_hub_for_git_repos">a home grown 'hub' for git repos</a>
|
||||
* <a href="#_general_syntax">general syntax</a>
|
||||
* <a href="#_Bob_s_commands">Bob's commands</a>
|
||||
* <a href="#_Alice_s_just_looking_commands">Alice's "just looking" commands</a>
|
||||
* <a href="#_Alice_s_action_commands">Alice's "action" commands</a>
|
||||
* <a href="#_what_next_">what next?</a>
|
||||
* <a href="#_note_to_the_admin_configuration_variables">note to the admin: configuration variables</a>
|
||||
|
||||
<a name="_a_home_grown_hub_for_git_repos"></a>
|
||||
|
||||
### a home grown 'hub' for git repos
|
||||
|
||||
This ADC (admin-defined command) helps collaboration among repos. The name is
|
||||
in honor of github, which is the primary host for gitolite itself.
|
||||
|
||||
[Note that github is a web-based service, and does a lot more, like comments,
|
||||
code reviews, etc., none of which are possible here. We're only talking about
|
||||
some basic stuff to make the most common operations easier. In particular,
|
||||
this system is not a replacement for normal project communications like
|
||||
email!]
|
||||
|
||||
**Conventions used**: all through the following description, we will assume
|
||||
that **Alice** has a repo **parent**, **Bob** has a fork of parent called
|
||||
**child**, and he is asking Alice to pull a branch he made called **b1** from
|
||||
child to parent.
|
||||
|
||||
In plain git (without using github or similar), the pull request process
|
||||
starts with an email from Bob to Alice, followed by Alice running a `git fetch
|
||||
<Bob's URL> b1` (optionally preceded by a `git remote add` for convenience of
|
||||
long term use). Until this happens she can't see much detail about the
|
||||
commits to be pulled.
|
||||
|
||||
**What this ADC does** is (a) collect all the pull requests she needs to look
|
||||
at in one place, and (b) allow her to examine the changes with any combination
|
||||
of `git log` and `git diff` options *without having to fetch the content
|
||||
first*, and (c) act as a trusted intermediary to allow Alice to fetch *just
|
||||
one branch* from Bob even if she does not have any access to Bob's repository!
|
||||
|
||||
In a situation where there may be lots of requests, being able to take a quick
|
||||
look at them (and possibly reject some), without having to pull down anything
|
||||
at all, could be very useful.
|
||||
|
||||
Once past that level, she could get the changes down to her workstation using
|
||||
`git fetch` as normal. With this ADC, however, she has another alternative:
|
||||
get them over to `parent` (her repo) on the same gitolite server, then later
|
||||
do a normal `git fetch [origin]` to get it to her workstation. This has the
|
||||
added advantage that other people, who may be watching her repo but not Bob's,
|
||||
now get to see what Bob sent her and send comments etc.
|
||||
|
||||
<a name="_general_syntax"></a>
|
||||
|
||||
### general syntax
|
||||
|
||||
The general syntax is
|
||||
|
||||
ssh git@server hub <hub-command> <args>
|
||||
|
||||
<a name="_Bob_s_commands"></a>
|
||||
|
||||
#### Bob's commands
|
||||
|
||||
The following commands do not cause a fetch, and should be quite fast:
|
||||
|
||||
* Bob sends a pull request for branch b1 to repo parent. Notice he does not
|
||||
mention Alice by name. This command expects a message to be piped/typed
|
||||
in via STDIN [this message is meant to be transient and is not stored long
|
||||
term; use email for more "permanent" communications].
|
||||
|
||||
echo "hi Alice, please pull" | request-pull child b1 [parent]
|
||||
|
||||
If `child` was created by a recent version of the 'fork' ADC (or the KDE
|
||||
'clone' ADC), which records the name of the parent repo on a fork, and it
|
||||
is *that* repo to which Bob wishes to send the pull request, the third
|
||||
argument is optional.
|
||||
|
||||
* Bob lists the status (fetched/rejected/pending) of pull requests he has
|
||||
made from his repo child to repo parent. (Note we don't say "accepted" but
|
||||
"fetched"; see later for why):
|
||||
|
||||
request-status child [parent]
|
||||
|
||||
The second argument is optional the same way as the 3rd argument in the
|
||||
previous command.
|
||||
|
||||
<a name="_Alice_s_just_looking_commands"></a>
|
||||
|
||||
#### Alice's "just looking" commands
|
||||
|
||||
* Alice lists requests waiting for her to check and possibly pull into
|
||||
parent. For each waiting pull request, she will see a serial number, the
|
||||
originating repo name (child, in our example), the requestor (Bob, here),
|
||||
and the branch/tag-name (b1) being pulled:
|
||||
|
||||
list-requests parent
|
||||
|
||||
* Alice views request # 1 waiting to be pulled into parent. Shows the same
|
||||
details as above for that request, followed by the message that Bob typed
|
||||
in when he ran `request-pull`:
|
||||
|
||||
view-request parent 1
|
||||
|
||||
* Alice views the log of the branch she is being asked to pull. Note that
|
||||
this does NOT involve a fetch, so it will be pretty fast. The log starts
|
||||
from b1, and stops at a SHA that represents any of the branches in parent.
|
||||
Alice can use any git-log options she wants to; for instance `--graph`,
|
||||
`--decorate`, `--boundary`, etc., could be quite useful. However, she
|
||||
can't use any GUI; it has to be 'git log':
|
||||
|
||||
view-log parent 1 <git log options>
|
||||
|
||||
Notice that the repo name Alice supplies is still her own, although the
|
||||
log comes from the child repo that Bob wants Alice to pull from. It's
|
||||
best if you think of this as "view the commits from pull request #1 in
|
||||
'parent'".
|
||||
|
||||
* Alice views the diff between arbitrary commits on child:
|
||||
|
||||
view-diff parent 1 <git diff options>
|
||||
|
||||
Again, she mentions *her* reponame but the diff's come from `child`. Also
|
||||
note that, due to restrictions on what characters are allowed in arguments
|
||||
to ADCs, you probably can't do things like `pu^` or `master~3`, and have
|
||||
to use SHAs instead.
|
||||
|
||||
<a name="_Alice_s_action_commands"></a>
|
||||
|
||||
#### Alice's "action" commands
|
||||
|
||||
* Alice doesn't like what she sees and decides to reject it. This command
|
||||
expects some text on STDIN as the rejection message:
|
||||
|
||||
echo "hi Bob, your patch needs work; see email" | reject parent 1
|
||||
|
||||
The following commands will actually fetch from child into parent, and may take
|
||||
time if the changes are large. However all this is on the server so it does
|
||||
not involve network traffic:
|
||||
|
||||
* Alice likes what she sees so far and wants to fetch the branch Bob is
|
||||
asking her to pull. Note that we are intentionally not using the word
|
||||
"accept", because this command does not (and cannot, since it is running
|
||||
on a bare repo on the server) do a pull. What it does is it fetches into
|
||||
a branch whose name will be `requests/child/b1`.
|
||||
|
||||
Note that when multiple requests from the same repo (child) for the same
|
||||
branch (b1) happen, each "fetch" overwrites the branch. This allows Bob
|
||||
to continually refine the branch he is requesting for a pull based on
|
||||
(presumably emailed) comments from Alice. In a way, this is a "remote
|
||||
tracking branch", just like `refs/remotes/origin/b1`.
|
||||
|
||||
fetch parent 1
|
||||
|
||||
<a name="_what_next_"></a>
|
||||
|
||||
### what next?
|
||||
|
||||
At this point, you're done with the `hub` ADC. However, all this is on the
|
||||
bare `parent.git` on the server, and nothing has hit Alice's workstation yet!
|
||||
Alice will still have to run a fetch or a pull on her workstation if she wants
|
||||
to check the code in detail, use a tool like gitk, and especially to
|
||||
compile/test it. *Then* she decides whether to accept or reject the request,
|
||||
which will have to be communicated via email, of course; see the second para
|
||||
of this document ;-)
|
||||
|
||||
Finally, note that Alice does not actually need to use the `fetch` subcommand.
|
||||
She can do the traditional thing and fetch Bob's repo/branch directly to her
|
||||
*workstation*.
|
||||
|
||||
<a name="_note_to_the_admin_configuration_variables"></a>
|
||||
|
||||
### note to the admin: configuration variables
|
||||
|
||||
There are 2 configuration variables. `BASE_FETCH_URL` should be set to a
|
||||
simple "read" URL (so it doesn't even have to be ssh) that almost anyone using
|
||||
this server can use. It's only used in producing the `git fetch` command
|
||||
mentioned just above.
|
||||
|
||||
`GL_FORKED_FROM` is set to `gl-forked-from` by default, but if your initials
|
||||
are `JM` you can set it to `kde-cloned-from` to save time and trouble ;-)
|
156
t/t67-hub
Normal file
156
t/t67-hub
Normal file
|
@ -0,0 +1,156 @@
|
|||
# vim: syn=sh:
|
||||
for bc in 0 1
|
||||
do
|
||||
cd $TESTDIR
|
||||
$TESTDIR/rollback || die "rollback failed"
|
||||
editrc GL_BIG_CONFIG $bc
|
||||
editrc GL_WILDREPOS 1
|
||||
|
||||
rm -rf /tmp/glt-adc
|
||||
mkdir /tmp/glt-adc || die "mkdir /tmp/glt-adc failed"
|
||||
cp ../contrib/adc/* /tmp/glt-adc
|
||||
echo "\$GL_ADC_PATH = '/tmp/glt-adc';" | addrc
|
||||
runremote rm -f .gitolite.down
|
||||
|
||||
# ----------
|
||||
|
||||
name "INTERNAL"
|
||||
echo "
|
||||
@alice = u1
|
||||
@bob = u2
|
||||
@parent = r1
|
||||
@child = r2
|
||||
|
||||
repo @parent
|
||||
RW+ = @alice
|
||||
RW = tester
|
||||
R = @bob
|
||||
|
||||
@children = child/CREATOR/..*
|
||||
repo @children
|
||||
C = @all
|
||||
RW+ = CREATOR
|
||||
" | ugc
|
||||
expect_push_ok "master -> master"
|
||||
|
||||
name "setup: parent gets some branches"
|
||||
cd ~/td
|
||||
runlocal git clone u1:r1
|
||||
cd r1
|
||||
mdc base1; mdc base2; mdc base3
|
||||
runlocal git branch p3
|
||||
runlocal git branch p2
|
||||
runlocal git branch p1
|
||||
mdc p1a; mdc p1b; mdc p1c
|
||||
runlocal git checkout p2
|
||||
mdc p2a; mdc p2b; mdc p2c
|
||||
runlocal git checkout p3
|
||||
mdc p3a; mdc p3b; mdc p3c
|
||||
runlocal git push origin --all
|
||||
expect To u1:r1
|
||||
expect "\* \[new branch\] master -> master"
|
||||
expect "\* \[new branch\] p1 -> p1"
|
||||
expect "\* \[new branch\] p2 -> p2"
|
||||
expect "\* \[new branch\] p3 -> p3"
|
||||
|
||||
name "setup: child is cloned and adds b1 and b2"
|
||||
cd ~/td
|
||||
runlocal ssh u2 fork r1 child/u2/myr1
|
||||
runremote ls -al repositories/child/u2/myr1.git/gl-forked-from
|
||||
expect "gitolite-test gitolite-test 3 .* repositories/child/u2/myr1.git/gl-forked-from"
|
||||
runremote cat repositories/child/u2/myr1.git/gl-forked-from
|
||||
expect r1
|
||||
runlocal git clone u2:child/u2/myr1
|
||||
cd myr1
|
||||
runlocal git checkout -b b1 origin/p1
|
||||
mdc c1
|
||||
runlocal git checkout -b b2 origin/p2
|
||||
mdc d1; mdc d2
|
||||
runlocal git checkout -b b3 origin/p3
|
||||
mdc e1; mdc e2; mdc e3
|
||||
runlocal git push origin b1 b2 b3
|
||||
expect To u2:child/u2/myr1
|
||||
expect "\* \[new branch\] b1 -> b1"
|
||||
expect "\* \[new branch\] b2 -> b2"
|
||||
expect "\* \[new branch\] b3 -> b3"
|
||||
|
||||
name "bob sends in a few pull requests"
|
||||
printf "hello\nthere" | runlocal ssh u2 hub request-pull child/u2/myr1 b1
|
||||
notexpect .
|
||||
printf "hi\nthere" | runlocal ssh u2 hub request-pull child/u2/myr1 b2
|
||||
notexpect .
|
||||
printf "hello\nagain" | runlocal ssh u2 hub request-pull child/u2/myr1 b3
|
||||
notexpect .
|
||||
|
||||
name "bob checks his pending requests"
|
||||
runlocal ssh u2 hub request-status child/u2/myr1
|
||||
expect "1 child/u2/myr1 (u2) b1 pending"
|
||||
expect "2 child/u2/myr1 (u2) b2 pending"
|
||||
expect "3 child/u2/myr1 (u2) b3 pending"
|
||||
|
||||
name "alice checks her pull requests"
|
||||
runlocal ssh u1 hub list-requests r1
|
||||
expect "1 child/u2/myr1 (u2) b1 pending"
|
||||
expect "2 child/u2/myr1 (u2) b2 pending"
|
||||
expect "3 child/u2/myr1 (u2) b3 pending"
|
||||
|
||||
name "alice views request 1"
|
||||
runlocal ssh u1 hub view-request r1 1
|
||||
expect "1 child/u2/myr1 (u2) b1 pending"
|
||||
expect ^hello
|
||||
expect ^there
|
||||
|
||||
name "alice views log and diffs"
|
||||
runlocal ssh u1 hub view-log r1 1
|
||||
expect "setup: child is cloned and adds b1 and b2"
|
||||
expect commit
|
||||
wc < ~/1 > ~/2; > ~/1
|
||||
expect "5 22 178"
|
||||
|
||||
runlocal ssh u1 hub view-log r1 3 --oneline
|
||||
expect "setup: child is cloned and adds b1 and b2"
|
||||
notexpect commit
|
||||
diffargs=`tac ~/1 | cut -f1 -d' ' | sed -n -e1p -e3p`
|
||||
wc < ~/1 > ~/2; > ~/1
|
||||
expect "3 30 150"
|
||||
|
||||
runlocal ssh u1 hub view-log r1 2 b1
|
||||
expect "fatal: ambiguous argument 'b1': unknown revision or path not in the working tree."
|
||||
|
||||
runlocal ssh u1 hub view-diff r1 3 $diffargs
|
||||
expect "diff.*e2"
|
||||
expect "diff.*e3"
|
||||
expect "new file mode"
|
||||
|
||||
name "alice tries to view a SHA she shouldnt"
|
||||
echo > ~/1
|
||||
echo > ~/2
|
||||
runlocal ssh u1 hub view-diff r1 2 $diffargs
|
||||
notexpect "diff.*e2"
|
||||
notexpect "diff.*e3"
|
||||
notexpect "new file mode"
|
||||
expect "invalid SHA:"
|
||||
|
||||
name "alice rejects 2, accepts 3"
|
||||
echo captain was sober today | runlocal ssh u1 hub reject r1 2
|
||||
notexpect .
|
||||
echo | runlocal ssh u1 hub fetch r1 3
|
||||
expect "user u2 asked you to"
|
||||
expect "git fetch git://gl.example.com/child/u2/myr1 b3"
|
||||
expect "From /home/gitolite-test/repositories/child/u2/myr1"
|
||||
expect "\* \[new branch\] b3 -> requests/child/b3"
|
||||
|
||||
name "bob checks his pending requests"
|
||||
runlocal ssh u2 hub request-status child/u2/myr1
|
||||
expect "1 child/u2/myr1 (u2) b1 pending"
|
||||
expect "2 child/u2/myr1 (u2) b2 rejected"
|
||||
expect "3 child/u2/myr1 (u2) b3 fetched"
|
||||
|
||||
name "alice checks her pull requests"
|
||||
runlocal ssh u1 hub list-requests r1
|
||||
expect "1 child/u2/myr1 (u2) b1 pending"
|
||||
expect "2 child/u2/myr1 (u2) b2 rejected"
|
||||
expect "3 child/u2/myr1 (u2) b3 fetched"
|
||||
|
||||
name "INTERNAL"
|
||||
done
|
Loading…
Reference in a new issue