]>
Commit | Line | Data |
---|---|---|
1 | #!/bin/sh | |
2 | # | |
3 | # git-submodule.sh: add, init, update or list git submodules | |
4 | # | |
5 | # Copyright (c) 2007 Lars Hjemli | |
6 | ||
7 | dashless=$(basename "$0" | sed -e 's/-/ /') | |
8 | USAGE="[--quiet] [--cached] | |
9 | or: $dashless [--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>] | |
10 | or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...] | |
11 | or: $dashless [--quiet] init [--] [<path>...] | |
12 | or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...) | |
13 | or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--[no-]single-branch] [--] [<path>...] | |
14 | or: $dashless [--quiet] set-branch (--default|--branch <branch>) [--] <path> | |
15 | or: $dashless [--quiet] set-url [--] <path> <newurl> | |
16 | or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...] | |
17 | or: $dashless [--quiet] foreach [--recursive] <command> | |
18 | or: $dashless [--quiet] sync [--recursive] [--] [<path>...] | |
19 | or: $dashless [--quiet] absorbgitdirs [--] [<path>...]" | |
20 | OPTIONS_SPEC= | |
21 | SUBDIRECTORY_OK=Yes | |
22 | . git-sh-setup | |
23 | . git-parse-remote | |
24 | require_work_tree | |
25 | wt_prefix=$(git rev-parse --show-prefix) | |
26 | cd_to_toplevel | |
27 | ||
28 | # Tell the rest of git that any URLs we get don't come | |
29 | # directly from the user, so it can apply policy as appropriate. | |
30 | GIT_PROTOCOL_FROM_USER=0 | |
31 | export GIT_PROTOCOL_FROM_USER | |
32 | ||
33 | command= | |
34 | branch= | |
35 | force= | |
36 | reference= | |
37 | cached= | |
38 | recursive= | |
39 | init= | |
40 | require_init= | |
41 | files= | |
42 | remote= | |
43 | nofetch= | |
44 | update= | |
45 | prefix= | |
46 | custom_name= | |
47 | depth= | |
48 | progress= | |
49 | dissociate= | |
50 | single_branch= | |
51 | jobs= | |
52 | recommend_shallow= | |
53 | ||
54 | die_if_unmatched () | |
55 | { | |
56 | if test "$1" = "#unmatched" | |
57 | then | |
58 | exit ${2:-1} | |
59 | fi | |
60 | } | |
61 | ||
62 | isnumber() | |
63 | { | |
64 | n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1" | |
65 | } | |
66 | ||
67 | # Given a full hex object ID, is this the zero OID? | |
68 | is_zero_oid () { | |
69 | echo "$1" | sane_egrep '^0+$' >/dev/null 2>&1 | |
70 | } | |
71 | ||
72 | # Sanitize the local git environment for use within a submodule. We | |
73 | # can't simply use clear_local_git_env since we want to preserve some | |
74 | # of the settings from GIT_CONFIG_PARAMETERS. | |
75 | sanitize_submodule_env() | |
76 | { | |
77 | save_config=$GIT_CONFIG_PARAMETERS | |
78 | clear_local_git_env | |
79 | GIT_CONFIG_PARAMETERS=$save_config | |
80 | export GIT_CONFIG_PARAMETERS | |
81 | } | |
82 | ||
83 | # | |
84 | # Add a new submodule to the working tree, .gitmodules and the index | |
85 | # | |
86 | # $@ = repo path | |
87 | # | |
88 | # optional branch is stored in global branch variable | |
89 | # | |
90 | cmd_add() | |
91 | { | |
92 | # parse $args after "submodule ... add". | |
93 | reference_path= | |
94 | while test $# -ne 0 | |
95 | do | |
96 | case "$1" in | |
97 | -b | --branch) | |
98 | case "$2" in '') usage ;; esac | |
99 | branch=$2 | |
100 | shift | |
101 | ;; | |
102 | -f | --force) | |
103 | force=$1 | |
104 | ;; | |
105 | -q|--quiet) | |
106 | GIT_QUIET=1 | |
107 | ;; | |
108 | --progress) | |
109 | progress=1 | |
110 | ;; | |
111 | --reference) | |
112 | case "$2" in '') usage ;; esac | |
113 | reference_path=$2 | |
114 | shift | |
115 | ;; | |
116 | --reference=*) | |
117 | reference_path="${1#--reference=}" | |
118 | ;; | |
119 | --dissociate) | |
120 | dissociate=1 | |
121 | ;; | |
122 | --name) | |
123 | case "$2" in '') usage ;; esac | |
124 | custom_name=$2 | |
125 | shift | |
126 | ;; | |
127 | --depth) | |
128 | case "$2" in '') usage ;; esac | |
129 | depth="--depth=$2" | |
130 | shift | |
131 | ;; | |
132 | --depth=*) | |
133 | depth=$1 | |
134 | ;; | |
135 | --) | |
136 | shift | |
137 | break | |
138 | ;; | |
139 | -*) | |
140 | usage | |
141 | ;; | |
142 | *) | |
143 | break | |
144 | ;; | |
145 | esac | |
146 | shift | |
147 | done | |
148 | ||
149 | if ! git submodule--helper config --check-writeable >/dev/null 2>&1 | |
150 | then | |
151 | die "$(eval_gettext "please make sure that the .gitmodules file is in the working tree")" | |
152 | fi | |
153 | ||
154 | if test -n "$reference_path" | |
155 | then | |
156 | is_absolute_path "$reference_path" || | |
157 | reference_path="$wt_prefix$reference_path" | |
158 | ||
159 | reference="--reference=$reference_path" | |
160 | fi | |
161 | ||
162 | repo=$1 | |
163 | sm_path=$2 | |
164 | ||
165 | if test -z "$sm_path"; then | |
166 | sm_path=$(printf '%s\n' "$repo" | | |
167 | sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g') | |
168 | fi | |
169 | ||
170 | if test -z "$repo" || test -z "$sm_path"; then | |
171 | usage | |
172 | fi | |
173 | ||
174 | is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path" | |
175 | ||
176 | # assure repo is absolute or relative to parent | |
177 | case "$repo" in | |
178 | ./*|../*) | |
179 | test -z "$wt_prefix" || | |
180 | die "$(gettext "Relative path can only be used from the toplevel of the working tree")" | |
181 | ||
182 | # dereference source url relative to parent's url | |
183 | realrepo=$(git submodule--helper resolve-relative-url "$repo") || exit | |
184 | ;; | |
185 | *:*|/*) | |
186 | # absolute url | |
187 | realrepo=$repo | |
188 | ;; | |
189 | *) | |
190 | die "$(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")" | |
191 | ;; | |
192 | esac | |
193 | ||
194 | # normalize path: | |
195 | # multiple //; leading ./; /./; /../; trailing / | |
196 | sm_path=$(printf '%s/\n' "$sm_path" | | |
197 | sed -e ' | |
198 | s|//*|/|g | |
199 | s|^\(\./\)*|| | |
200 | s|/\(\./\)*|/|g | |
201 | :start | |
202 | s|\([^/]*\)/\.\./|| | |
203 | tstart | |
204 | s|/*$|| | |
205 | ') | |
206 | if test -z "$force" | |
207 | then | |
208 | git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 && | |
209 | die "$(eval_gettext "'\$sm_path' already exists in the index")" | |
210 | else | |
211 | git ls-files -s "$sm_path" | sane_grep -v "^160000" > /dev/null 2>&1 && | |
212 | die "$(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")" | |
213 | fi | |
214 | ||
215 | if test -d "$sm_path" && | |
216 | test -z $(git -C "$sm_path" rev-parse --show-cdup 2>/dev/null) | |
217 | then | |
218 | git -C "$sm_path" rev-parse --verify -q HEAD >/dev/null || | |
219 | die "$(eval_gettext "'\$sm_path' does not have a commit checked out")" | |
220 | fi | |
221 | ||
222 | if test -z "$force" | |
223 | then | |
224 | dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" 2>&1 >/dev/null) | |
225 | res=$? | |
226 | if test $res -ne 0 | |
227 | then | |
228 | echo >&2 "$dryerr" | |
229 | exit $res | |
230 | fi | |
231 | fi | |
232 | ||
233 | if test -n "$custom_name" | |
234 | then | |
235 | sm_name="$custom_name" | |
236 | else | |
237 | sm_name="$sm_path" | |
238 | fi | |
239 | ||
240 | if ! git submodule--helper check-name "$sm_name" | |
241 | then | |
242 | die "$(eval_gettext "'$sm_name' is not a valid submodule name")" | |
243 | fi | |
244 | ||
245 | # perhaps the path exists and is already a git repo, else clone it | |
246 | if test -e "$sm_path" | |
247 | then | |
248 | if test -d "$sm_path"/.git || test -f "$sm_path"/.git | |
249 | then | |
250 | eval_gettextln "Adding existing repo at '\$sm_path' to the index" | |
251 | else | |
252 | die "$(eval_gettext "'\$sm_path' already exists and is not a valid git repo")" | |
253 | fi | |
254 | ||
255 | else | |
256 | if test -d ".git/modules/$sm_name" | |
257 | then | |
258 | if test -z "$force" | |
259 | then | |
260 | eval_gettextln >&2 "A git directory for '\$sm_name' is found locally with remote(s):" | |
261 | GIT_DIR=".git/modules/$sm_name" GIT_WORK_TREE=. git remote -v | grep '(fetch)' | sed -e s,^," ", -e s,' (fetch)',, >&2 | |
262 | die "$(eval_gettextln "\ | |
263 | If you want to reuse this local git directory instead of cloning again from | |
264 | \$realrepo | |
265 | use the '--force' option. If the local git directory is not the correct repo | |
266 | or you are unsure what this means choose another name with the '--name' option.")" | |
267 | else | |
268 | eval_gettextln "Reactivating local git directory for submodule '\$sm_name'." | |
269 | fi | |
270 | fi | |
271 | git submodule--helper clone ${GIT_QUIET:+--quiet} ${progress:+"--progress"} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${dissociate:+"--dissociate"} ${depth:+"$depth"} || exit | |
272 | ( | |
273 | sanitize_submodule_env | |
274 | cd "$sm_path" && | |
275 | # ash fails to wordsplit ${branch:+-b "$branch"...} | |
276 | case "$branch" in | |
277 | '') git checkout -f -q ;; | |
278 | ?*) git checkout -f -q -B "$branch" "origin/$branch" ;; | |
279 | esac | |
280 | ) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")" | |
281 | fi | |
282 | git config submodule."$sm_name".url "$realrepo" | |
283 | ||
284 | git add --no-warn-embedded-repo $force "$sm_path" || | |
285 | die "$(eval_gettext "Failed to add submodule '\$sm_path'")" | |
286 | ||
287 | git submodule--helper config submodule."$sm_name".path "$sm_path" && | |
288 | git submodule--helper config submodule."$sm_name".url "$repo" && | |
289 | if test -n "$branch" | |
290 | then | |
291 | git submodule--helper config submodule."$sm_name".branch "$branch" | |
292 | fi && | |
293 | git add --force .gitmodules || | |
294 | die "$(eval_gettext "Failed to register submodule '\$sm_path'")" | |
295 | ||
296 | # NEEDSWORK: In a multi-working-tree world, this needs to be | |
297 | # set in the per-worktree config. | |
298 | if git config --get submodule.active >/dev/null | |
299 | then | |
300 | # If the submodule being adding isn't already covered by the | |
301 | # current configured pathspec, set the submodule's active flag | |
302 | if ! git submodule--helper is-active "$sm_path" | |
303 | then | |
304 | git config submodule."$sm_name".active "true" | |
305 | fi | |
306 | else | |
307 | git config submodule."$sm_name".active "true" | |
308 | fi | |
309 | } | |
310 | ||
311 | # | |
312 | # Execute an arbitrary command sequence in each checked out | |
313 | # submodule | |
314 | # | |
315 | # $@ = command to execute | |
316 | # | |
317 | cmd_foreach() | |
318 | { | |
319 | # parse $args after "submodule ... foreach". | |
320 | while test $# -ne 0 | |
321 | do | |
322 | case "$1" in | |
323 | -q|--quiet) | |
324 | GIT_QUIET=1 | |
325 | ;; | |
326 | --recursive) | |
327 | recursive=1 | |
328 | ;; | |
329 | -*) | |
330 | usage | |
331 | ;; | |
332 | *) | |
333 | break | |
334 | ;; | |
335 | esac | |
336 | shift | |
337 | done | |
338 | ||
339 | git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper foreach ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@" | |
340 | } | |
341 | ||
342 | # | |
343 | # Register submodules in .git/config | |
344 | # | |
345 | # $@ = requested paths (default to all) | |
346 | # | |
347 | cmd_init() | |
348 | { | |
349 | # parse $args after "submodule ... init". | |
350 | while test $# -ne 0 | |
351 | do | |
352 | case "$1" in | |
353 | -q|--quiet) | |
354 | GIT_QUIET=1 | |
355 | ;; | |
356 | --) | |
357 | shift | |
358 | break | |
359 | ;; | |
360 | -*) | |
361 | usage | |
362 | ;; | |
363 | *) | |
364 | break | |
365 | ;; | |
366 | esac | |
367 | shift | |
368 | done | |
369 | ||
370 | git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper init ${GIT_QUIET:+--quiet} -- "$@" | |
371 | } | |
372 | ||
373 | # | |
374 | # Unregister submodules from .git/config and remove their work tree | |
375 | # | |
376 | cmd_deinit() | |
377 | { | |
378 | # parse $args after "submodule ... deinit". | |
379 | deinit_all= | |
380 | while test $# -ne 0 | |
381 | do | |
382 | case "$1" in | |
383 | -f|--force) | |
384 | force=$1 | |
385 | ;; | |
386 | -q|--quiet) | |
387 | GIT_QUIET=1 | |
388 | ;; | |
389 | --all) | |
390 | deinit_all=t | |
391 | ;; | |
392 | --) | |
393 | shift | |
394 | break | |
395 | ;; | |
396 | -*) | |
397 | usage | |
398 | ;; | |
399 | *) | |
400 | break | |
401 | ;; | |
402 | esac | |
403 | shift | |
404 | done | |
405 | ||
406 | git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${prefix:+--prefix "$prefix"} ${force:+--force} ${deinit_all:+--all} -- "$@" | |
407 | } | |
408 | ||
409 | is_tip_reachable () ( | |
410 | sanitize_submodule_env && | |
411 | cd "$1" && | |
412 | rev=$(git rev-list -n 1 "$2" --not --all 2>/dev/null) && | |
413 | test -z "$rev" | |
414 | ) | |
415 | ||
416 | fetch_in_submodule () ( | |
417 | sanitize_submodule_env && | |
418 | cd "$1" && | |
419 | case "$2" in | |
420 | '') | |
421 | git fetch ;; | |
422 | *) | |
423 | shift | |
424 | git fetch $(get_default_remote) "$@" ;; | |
425 | esac | |
426 | ) | |
427 | ||
428 | # | |
429 | # Update each submodule path to correct revision, using clone and checkout as needed | |
430 | # | |
431 | # $@ = requested paths (default to all) | |
432 | # | |
433 | cmd_update() | |
434 | { | |
435 | # parse $args after "submodule ... update". | |
436 | while test $# -ne 0 | |
437 | do | |
438 | case "$1" in | |
439 | -q|--quiet) | |
440 | GIT_QUIET=1 | |
441 | ;; | |
442 | -v) | |
443 | GIT_QUIET=0 | |
444 | ;; | |
445 | --progress) | |
446 | progress=1 | |
447 | ;; | |
448 | -i|--init) | |
449 | init=1 | |
450 | ;; | |
451 | --require-init) | |
452 | init=1 | |
453 | require_init=1 | |
454 | ;; | |
455 | --remote) | |
456 | remote=1 | |
457 | ;; | |
458 | -N|--no-fetch) | |
459 | nofetch=1 | |
460 | ;; | |
461 | -f|--force) | |
462 | force=$1 | |
463 | ;; | |
464 | -r|--rebase) | |
465 | update="rebase" | |
466 | ;; | |
467 | --reference) | |
468 | case "$2" in '') usage ;; esac | |
469 | reference="--reference=$2" | |
470 | shift | |
471 | ;; | |
472 | --reference=*) | |
473 | reference="$1" | |
474 | ;; | |
475 | --dissociate) | |
476 | dissociate=1 | |
477 | ;; | |
478 | -m|--merge) | |
479 | update="merge" | |
480 | ;; | |
481 | --recursive) | |
482 | recursive=1 | |
483 | ;; | |
484 | --checkout) | |
485 | update="checkout" | |
486 | ;; | |
487 | --recommend-shallow) | |
488 | recommend_shallow="--recommend-shallow" | |
489 | ;; | |
490 | --no-recommend-shallow) | |
491 | recommend_shallow="--no-recommend-shallow" | |
492 | ;; | |
493 | --depth) | |
494 | case "$2" in '') usage ;; esac | |
495 | depth="--depth=$2" | |
496 | shift | |
497 | ;; | |
498 | --depth=*) | |
499 | depth=$1 | |
500 | ;; | |
501 | -j|--jobs) | |
502 | case "$2" in '') usage ;; esac | |
503 | jobs="--jobs=$2" | |
504 | shift | |
505 | ;; | |
506 | --jobs=*) | |
507 | jobs=$1 | |
508 | ;; | |
509 | --single-branch) | |
510 | single_branch="--single-branch" | |
511 | ;; | |
512 | --no-single-branch) | |
513 | single_branch="--no-single-branch" | |
514 | ;; | |
515 | --) | |
516 | shift | |
517 | break | |
518 | ;; | |
519 | -*) | |
520 | usage | |
521 | ;; | |
522 | *) | |
523 | break | |
524 | ;; | |
525 | esac | |
526 | shift | |
527 | done | |
528 | ||
529 | if test -n "$init" | |
530 | then | |
531 | cmd_init "--" "$@" || return | |
532 | fi | |
533 | ||
534 | { | |
535 | git submodule--helper update-clone ${GIT_QUIET:+--quiet} \ | |
536 | ${progress:+"--progress"} \ | |
537 | ${wt_prefix:+--prefix "$wt_prefix"} \ | |
538 | ${prefix:+--recursive-prefix "$prefix"} \ | |
539 | ${update:+--update "$update"} \ | |
540 | ${reference:+"$reference"} \ | |
541 | ${dissociate:+"--dissociate"} \ | |
542 | ${depth:+--depth "$depth"} \ | |
543 | ${require_init:+--require-init} \ | |
544 | $single_branch \ | |
545 | $recommend_shallow \ | |
546 | $jobs \ | |
547 | -- \ | |
548 | "$@" || echo "#unmatched" $? | |
549 | } | { | |
550 | err= | |
551 | while read -r quickabort sha1 just_cloned sm_path | |
552 | do | |
553 | die_if_unmatched "$quickabort" "$sha1" | |
554 | ||
555 | git submodule--helper ensure-core-worktree "$sm_path" || exit 1 | |
556 | ||
557 | update_module=$(git submodule--helper update-module-mode $just_cloned "$sm_path" $update) | |
558 | ||
559 | displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix") | |
560 | ||
561 | if test $just_cloned -eq 1 | |
562 | then | |
563 | subsha1= | |
564 | else | |
565 | subsha1=$(sanitize_submodule_env; cd "$sm_path" && | |
566 | git rev-parse --verify HEAD) || | |
567 | die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")" | |
568 | fi | |
569 | ||
570 | if test -n "$remote" | |
571 | then | |
572 | branch=$(git submodule--helper remote-branch "$sm_path") | |
573 | if test -z "$nofetch" | |
574 | then | |
575 | # Fetch remote before determining tracking $sha1 | |
576 | fetch_in_submodule "$sm_path" $depth || | |
577 | die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")" | |
578 | fi | |
579 | remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote) | |
580 | sha1=$(sanitize_submodule_env; cd "$sm_path" && | |
581 | git rev-parse --verify "${remote_name}/${branch}") || | |
582 | die "$(eval_gettext "Unable to find current \${remote_name}/\${branch} revision in submodule path '\$sm_path'")" | |
583 | fi | |
584 | ||
585 | if test "$subsha1" != "$sha1" || test -n "$force" | |
586 | then | |
587 | subforce=$force | |
588 | # If we don't already have a -f flag and the submodule has never been checked out | |
589 | if test -z "$subsha1" && test -z "$force" | |
590 | then | |
591 | subforce="-f" | |
592 | fi | |
593 | ||
594 | if test -z "$nofetch" | |
595 | then | |
596 | # Run fetch only if $sha1 isn't present or it | |
597 | # is not reachable from a ref. | |
598 | is_tip_reachable "$sm_path" "$sha1" || | |
599 | fetch_in_submodule "$sm_path" $depth || | |
600 | say "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'; trying to directly fetch \$sha1:")" | |
601 | ||
602 | # Now we tried the usual fetch, but $sha1 may | |
603 | # not be reachable from any of the refs | |
604 | is_tip_reachable "$sm_path" "$sha1" || | |
605 | fetch_in_submodule "$sm_path" $depth "$sha1" || | |
606 | die "$(eval_gettext "Fetched in submodule path '\$displaypath', but it did not contain \$sha1. Direct fetching of that commit failed.")" | |
607 | fi | |
608 | ||
609 | must_die_on_failure= | |
610 | case "$update_module" in | |
611 | checkout) | |
612 | command="git checkout $subforce -q" | |
613 | die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")" | |
614 | say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")" | |
615 | ;; | |
616 | rebase) | |
617 | command="git rebase" | |
618 | die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")" | |
619 | say_msg="$(eval_gettext "Submodule path '\$displaypath': rebased into '\$sha1'")" | |
620 | must_die_on_failure=yes | |
621 | ;; | |
622 | merge) | |
623 | command="git merge" | |
624 | die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$displaypath'")" | |
625 | say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")" | |
626 | must_die_on_failure=yes | |
627 | ;; | |
628 | !*) | |
629 | command="${update_module#!}" | |
630 | die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$displaypath'")" | |
631 | say_msg="$(eval_gettext "Submodule path '\$displaypath': '\$command \$sha1'")" | |
632 | must_die_on_failure=yes | |
633 | ;; | |
634 | *) | |
635 | die "$(eval_gettext "Invalid update mode '$update_module' for submodule path '$path'")" | |
636 | esac | |
637 | ||
638 | if (sanitize_submodule_env; cd "$sm_path" && $command "$sha1") | |
639 | then | |
640 | say "$say_msg" | |
641 | elif test -n "$must_die_on_failure" | |
642 | then | |
643 | die_with_status 2 "$die_msg" | |
644 | else | |
645 | err="${err};$die_msg" | |
646 | continue | |
647 | fi | |
648 | fi | |
649 | ||
650 | if test -n "$recursive" | |
651 | then | |
652 | ( | |
653 | prefix=$(git submodule--helper relative-path "$prefix$sm_path/" "$wt_prefix") | |
654 | wt_prefix= | |
655 | sanitize_submodule_env | |
656 | cd "$sm_path" && | |
657 | eval cmd_update | |
658 | ) | |
659 | res=$? | |
660 | if test $res -gt 0 | |
661 | then | |
662 | die_msg="$(eval_gettext "Failed to recurse into submodule path '\$displaypath'")" | |
663 | if test $res -ne 2 | |
664 | then | |
665 | err="${err};$die_msg" | |
666 | continue | |
667 | else | |
668 | die_with_status $res "$die_msg" | |
669 | fi | |
670 | fi | |
671 | fi | |
672 | done | |
673 | ||
674 | if test -n "$err" | |
675 | then | |
676 | OIFS=$IFS | |
677 | IFS=';' | |
678 | for e in $err | |
679 | do | |
680 | if test -n "$e" | |
681 | then | |
682 | echo >&2 "$e" | |
683 | fi | |
684 | done | |
685 | IFS=$OIFS | |
686 | exit 1 | |
687 | fi | |
688 | } | |
689 | } | |
690 | ||
691 | # | |
692 | # Configures a submodule's default branch | |
693 | # | |
694 | # $@ = requested path | |
695 | # | |
696 | cmd_set_branch() { | |
697 | default= | |
698 | branch= | |
699 | ||
700 | while test $# -ne 0 | |
701 | do | |
702 | case "$1" in | |
703 | -q|--quiet) | |
704 | # we don't do anything with this but we need to accept it | |
705 | ;; | |
706 | -d|--default) | |
707 | default=1 | |
708 | ;; | |
709 | -b|--branch) | |
710 | case "$2" in '') usage ;; esac | |
711 | branch=$2 | |
712 | shift | |
713 | ;; | |
714 | --) | |
715 | shift | |
716 | break | |
717 | ;; | |
718 | -*) | |
719 | usage | |
720 | ;; | |
721 | *) | |
722 | break | |
723 | ;; | |
724 | esac | |
725 | shift | |
726 | done | |
727 | ||
728 | git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper set-branch ${GIT_QUIET:+--quiet} ${branch:+--branch "$branch"} ${default:+--default} -- "$@" | |
729 | } | |
730 | ||
731 | # | |
732 | # Configures a submodule's remote url | |
733 | # | |
734 | # $@ = requested path, requested url | |
735 | # | |
736 | cmd_set_url() { | |
737 | while test $# -ne 0 | |
738 | do | |
739 | case "$1" in | |
740 | -q|--quiet) | |
741 | GIT_QUIET=1 | |
742 | ;; | |
743 | --) | |
744 | shift | |
745 | break | |
746 | ;; | |
747 | -*) | |
748 | usage | |
749 | ;; | |
750 | *) | |
751 | break | |
752 | ;; | |
753 | esac | |
754 | shift | |
755 | done | |
756 | ||
757 | git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper set-url ${GIT_QUIET:+--quiet} -- "$@" | |
758 | } | |
759 | ||
760 | # | |
761 | # Show commit summary for submodules in index or working tree | |
762 | # | |
763 | # If '--cached' is given, show summary between index and given commit, | |
764 | # or between working tree and given commit | |
765 | # | |
766 | # $@ = [commit (default 'HEAD'),] requested paths (default all) | |
767 | # | |
768 | cmd_summary() { | |
769 | summary_limit=-1 | |
770 | for_status= | |
771 | diff_cmd=diff-index | |
772 | ||
773 | # parse $args after "submodule ... summary". | |
774 | while test $# -ne 0 | |
775 | do | |
776 | case "$1" in | |
777 | --cached) | |
778 | cached="$1" | |
779 | ;; | |
780 | --files) | |
781 | files="$1" | |
782 | ;; | |
783 | --for-status) | |
784 | for_status="$1" | |
785 | ;; | |
786 | -n|--summary-limit) | |
787 | summary_limit="$2" | |
788 | isnumber "$summary_limit" || usage | |
789 | shift | |
790 | ;; | |
791 | --summary-limit=*) | |
792 | summary_limit="${1#--summary-limit=}" | |
793 | isnumber "$summary_limit" || usage | |
794 | ;; | |
795 | --) | |
796 | shift | |
797 | break | |
798 | ;; | |
799 | -*) | |
800 | usage | |
801 | ;; | |
802 | *) | |
803 | break | |
804 | ;; | |
805 | esac | |
806 | shift | |
807 | done | |
808 | ||
809 | git ${wt_prefix:+-C "$wt_prefix"} submodule--helper summary ${prefix:+--prefix "$prefix"} ${files:+--files} ${cached:+--cached} ${for_status:+--for-status} ${summary_limit:+-n $summary_limit} -- "$@" | |
810 | } | |
811 | # | |
812 | # List all submodules, prefixed with: | |
813 | # - submodule not initialized | |
814 | # + different revision checked out | |
815 | # | |
816 | # If --cached was specified the revision in the index will be printed | |
817 | # instead of the currently checked out revision. | |
818 | # | |
819 | # $@ = requested paths (default to all) | |
820 | # | |
821 | cmd_status() | |
822 | { | |
823 | # parse $args after "submodule ... status". | |
824 | while test $# -ne 0 | |
825 | do | |
826 | case "$1" in | |
827 | -q|--quiet) | |
828 | GIT_QUIET=1 | |
829 | ;; | |
830 | --cached) | |
831 | cached=1 | |
832 | ;; | |
833 | --recursive) | |
834 | recursive=1 | |
835 | ;; | |
836 | --) | |
837 | shift | |
838 | break | |
839 | ;; | |
840 | -*) | |
841 | usage | |
842 | ;; | |
843 | *) | |
844 | break | |
845 | ;; | |
846 | esac | |
847 | shift | |
848 | done | |
849 | ||
850 | git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper status ${GIT_QUIET:+--quiet} ${cached:+--cached} ${recursive:+--recursive} -- "$@" | |
851 | } | |
852 | # | |
853 | # Sync remote urls for submodules | |
854 | # This makes the value for remote.$remote.url match the value | |
855 | # specified in .gitmodules. | |
856 | # | |
857 | cmd_sync() | |
858 | { | |
859 | while test $# -ne 0 | |
860 | do | |
861 | case "$1" in | |
862 | -q|--quiet) | |
863 | GIT_QUIET=1 | |
864 | shift | |
865 | ;; | |
866 | --recursive) | |
867 | recursive=1 | |
868 | shift | |
869 | ;; | |
870 | --) | |
871 | shift | |
872 | break | |
873 | ;; | |
874 | -*) | |
875 | usage | |
876 | ;; | |
877 | *) | |
878 | break | |
879 | ;; | |
880 | esac | |
881 | done | |
882 | ||
883 | git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper sync ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@" | |
884 | } | |
885 | ||
886 | cmd_absorbgitdirs() | |
887 | { | |
888 | git submodule--helper absorb-git-dirs --prefix "$wt_prefix" "$@" | |
889 | } | |
890 | ||
891 | # This loop parses the command line arguments to find the | |
892 | # subcommand name to dispatch. Parsing of the subcommand specific | |
893 | # options are primarily done by the subcommand implementations. | |
894 | # Subcommand specific options such as --branch and --cached are | |
895 | # parsed here as well, for backward compatibility. | |
896 | ||
897 | while test $# != 0 && test -z "$command" | |
898 | do | |
899 | case "$1" in | |
900 | add | foreach | init | deinit | update | set-branch | set-url | status | summary | sync | absorbgitdirs) | |
901 | command=$1 | |
902 | ;; | |
903 | -q|--quiet) | |
904 | GIT_QUIET=1 | |
905 | ;; | |
906 | -b|--branch) | |
907 | case "$2" in | |
908 | '') | |
909 | usage | |
910 | ;; | |
911 | esac | |
912 | branch="$2"; shift | |
913 | ;; | |
914 | --cached) | |
915 | cached="$1" | |
916 | ;; | |
917 | --) | |
918 | break | |
919 | ;; | |
920 | -*) | |
921 | usage | |
922 | ;; | |
923 | *) | |
924 | break | |
925 | ;; | |
926 | esac | |
927 | shift | |
928 | done | |
929 | ||
930 | # No command word defaults to "status" | |
931 | if test -z "$command" | |
932 | then | |
933 | if test $# = 0 | |
934 | then | |
935 | command=status | |
936 | else | |
937 | usage | |
938 | fi | |
939 | fi | |
940 | ||
941 | # "-b branch" is accepted only by "add" and "set-branch" | |
942 | if test -n "$branch" && (test "$command" != add || test "$command" != set-branch) | |
943 | then | |
944 | usage | |
945 | fi | |
946 | ||
947 | # "--cached" is accepted only by "status" and "summary" | |
948 | if test -n "$cached" && test "$command" != status && test "$command" != summary | |
949 | then | |
950 | usage | |
951 | fi | |
952 | ||
953 | "cmd_$(echo $command | sed -e s/-/_/g)" "$@" |