1 |
Long story short, our HEAD was set by 'git init' and left at the default |
2 |
'master'. So whenever we hit a repository that used a different default |
3 |
branch, we either fetched the wrong branch or failed completely. |
4 |
|
5 |
Using 'git clone' would fix the issue only temporarily since it does not |
6 |
provide a way to follow changes of the 'HEAD' branch. git has some code |
7 |
to obtain symbolic 'HEAD' using some of the transports but it seems not |
8 |
to be part of the command-line API. |
9 |
|
10 |
So instead, we do pretty much the same as 'git clone' does when it is |
11 |
unable to get the symbolic HEAD from remote. We find the branch that is |
12 |
on the same commit as HEAD, preferably 'master'. |
13 |
|
14 |
As a note: we need to fetch into a custom ref since git does not allow |
15 |
fetching to 'HEAD' directly. In fact, 'git fetch HEAD:HEAD' only creates |
16 |
a branch named 'HEAD', and 'git fetch --prune HEAD:HEAD' creates and |
17 |
removes it ;). |
18 |
--- |
19 |
eclass/git-r3.eclass | 42 ++++++++++++++++++++++++++++++++++++++++++ |
20 |
1 file changed, 42 insertions(+) |
21 |
|
22 |
diff --git a/eclass/git-r3.eclass b/eclass/git-r3.eclass |
23 |
index 892ed07..7c78b66 100644 |
24 |
--- a/eclass/git-r3.eclass |
25 |
+++ b/eclass/git-r3.eclass |
26 |
@@ -270,6 +270,42 @@ _git-r3_is_local_repo() { |
27 |
[[ ${uri} == file://* || ${uri} == /* ]] |
28 |
} |
29 |
|
30 |
+# @FUNCTION: _git-r3_update_head |
31 |
+# @USAGE: <remote-head-ref> |
32 |
+# @INTERNAL |
33 |
+# @DESCRIPTION: |
34 |
+# Given a ref to which remote HEAD was fetched, try to match |
35 |
+# a local branch and update symbolic HEAD appropriately. |
36 |
+_git-r3_update_head() |
37 |
+{ |
38 |
+ debug-print-function ${FUNCNAME} "$@" |
39 |
+ |
40 |
+ local head_ref=${1} |
41 |
+ local head_hash=$(git rev-parse --verify ${1} || die) |
42 |
+ local matching_ref |
43 |
+ |
44 |
+ # TODO: some transports support peeking at symbolic remote refs |
45 |
+ # find a way to use that rather than guessing |
46 |
+ |
47 |
+ # (based on guess_remote_head() in git-1.9.0/remote.c) |
48 |
+ local h ref |
49 |
+ while read h ref; do |
50 |
+ # look for matching head |
51 |
+ if [[ ${h} == ${head_hash} ]]; then |
52 |
+ # either take the first matching ref, or master if it is there |
53 |
+ if [[ ! ${matching_ref} || ${ref} == refs/heads/master ]]; then |
54 |
+ matching_ref=${ref} |
55 |
+ fi |
56 |
+ fi |
57 |
+ done < <(git show-ref --heads || die) |
58 |
+ |
59 |
+ if [[ ! ${matching_ref} ]]; then |
60 |
+ die "Unable to find a matching branch for remote HEAD (${head_hash})" |
61 |
+ fi |
62 |
+ |
63 |
+ git symbolic-ref HEAD "${matching_ref}" || die |
64 |
+} |
65 |
+ |
66 |
# @FUNCTION: git-r3_fetch |
67 |
# @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]] |
68 |
# @DESCRIPTION: |
69 |
@@ -335,11 +371,17 @@ git-r3_fetch() { |
70 |
"refs/tags/*:refs/tags/*" |
71 |
# notes in case something needs them |
72 |
"refs/notes/*:refs/notes/*" |
73 |
+ # and HEAD in case we need the default branch |
74 |
+ # (we keep it in refs/git-r3 since otherwise --prune interferes) |
75 |
+ HEAD:refs/git-r3/HEAD |
76 |
) |
77 |
|
78 |
set -- "${fetch_command[@]}" |
79 |
echo "${@}" >&2 |
80 |
if "${@}"; then |
81 |
+ # find remote HEAD and update our HEAD properly |
82 |
+ _git-r3_update_head refs/git-r3/HEAD |
83 |
+ |
84 |
# now let's see what the user wants from us |
85 |
local full_remote_ref=$( |
86 |
git rev-parse --verify --symbolic-full-name "${remote_ref}" |
87 |
-- |
88 |
1.8.3.2 |