reset: make sparse-aware (except --mixed)
[git.git] / git-submodule.sh
blob652861aa66a400940c24ea8405177f372009eafe
1 #!/bin/sh
3 # git-submodule.sh: add, init, update or list git submodules
5 # Copyright (c) 2007 Lars Hjemli
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 require_work_tree
24 wt_prefix=$(git rev-parse --show-prefix)
25 cd_to_toplevel
27 # Tell the rest of git that any URLs we get don't come
28 # directly from the user, so it can apply policy as appropriate.
29 GIT_PROTOCOL_FROM_USER=0
30 export GIT_PROTOCOL_FROM_USER
32 command=
33 branch=
34 force=
35 reference=
36 cached=
37 recursive=
38 init=
39 require_init=
40 files=
41 remote=
42 nofetch=
43 update=
44 prefix=
45 custom_name=
46 depth=
47 progress=
48 dissociate=
49 single_branch=
50 jobs=
51 recommend_shallow=
53 die_if_unmatched ()
55 if test "$1" = "#unmatched"
56 then
57 exit ${2:-1}
61 isnumber()
63 n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
66 # Sanitize the local git environment for use within a submodule. We
67 # can't simply use clear_local_git_env since we want to preserve some
68 # of the settings from GIT_CONFIG_PARAMETERS.
69 sanitize_submodule_env()
71 save_config=$GIT_CONFIG_PARAMETERS
72 clear_local_git_env
73 GIT_CONFIG_PARAMETERS=$save_config
74 export GIT_CONFIG_PARAMETERS
78 # Add a new submodule to the working tree, .gitmodules and the index
80 # $@ = repo path
82 # optional branch is stored in global branch variable
84 cmd_add()
86 # parse $args after "submodule ... add".
87 reference_path=
88 while test $# -ne 0
90 case "$1" in
91 -b | --branch)
92 case "$2" in '') usage ;; esac
93 branch=$2
94 shift
96 -f | --force)
97 force=$1
99 -q|--quiet)
100 GIT_QUIET=1
102 --progress)
103 progress=1
105 --reference)
106 case "$2" in '') usage ;; esac
107 reference_path=$2
108 shift
110 --reference=*)
111 reference_path="${1#--reference=}"
113 --dissociate)
114 dissociate=1
116 --name)
117 case "$2" in '') usage ;; esac
118 custom_name=$2
119 shift
121 --depth)
122 case "$2" in '') usage ;; esac
123 depth="--depth=$2"
124 shift
126 --depth=*)
127 depth=$1
130 shift
131 break
134 usage
137 break
139 esac
140 shift
141 done
143 if test -z "$1"
144 then
145 usage
148 git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper add ${GIT_QUIET:+--quiet} ${force:+--force} ${progress:+"--progress"} ${branch:+--branch "$branch"} ${reference_path:+--reference "$reference_path"} ${dissociate:+--dissociate} ${custom_name:+--name "$custom_name"} ${depth:+"$depth"} -- "$@"
152 # Execute an arbitrary command sequence in each checked out
153 # submodule
155 # $@ = command to execute
157 cmd_foreach()
159 # parse $args after "submodule ... foreach".
160 while test $# -ne 0
162 case "$1" in
163 -q|--quiet)
164 GIT_QUIET=1
166 --recursive)
167 recursive=1
170 usage
173 break
175 esac
176 shift
177 done
179 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper foreach ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@"
183 # Register submodules in .git/config
185 # $@ = requested paths (default to all)
187 cmd_init()
189 # parse $args after "submodule ... init".
190 while test $# -ne 0
192 case "$1" in
193 -q|--quiet)
194 GIT_QUIET=1
197 shift
198 break
201 usage
204 break
206 esac
207 shift
208 done
210 git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper init ${GIT_QUIET:+--quiet} -- "$@"
214 # Unregister submodules from .git/config and remove their work tree
216 cmd_deinit()
218 # parse $args after "submodule ... deinit".
219 deinit_all=
220 while test $# -ne 0
222 case "$1" in
223 -f|--force)
224 force=$1
226 -q|--quiet)
227 GIT_QUIET=1
229 --all)
230 deinit_all=t
233 shift
234 break
237 usage
240 break
242 esac
243 shift
244 done
246 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${force:+--force} ${deinit_all:+--all} -- "$@"
249 # usage: fetch_in_submodule <module_path> [<depth>] [<sha1>]
250 # Because arguments are positional, use an empty string to omit <depth>
251 # but include <sha1>.
252 fetch_in_submodule () (
253 sanitize_submodule_env &&
254 cd "$1" &&
255 if test $# -eq 3
256 then
257 echo "$3" | git fetch ${GIT_QUIET:+--quiet} --stdin ${2:+"$2"}
258 else
259 git fetch ${GIT_QUIET:+--quiet} ${2:+"$2"}
264 # Update each submodule path to correct revision, using clone and checkout as needed
266 # $@ = requested paths (default to all)
268 cmd_update()
270 # parse $args after "submodule ... update".
271 while test $# -ne 0
273 case "$1" in
274 -q|--quiet)
275 GIT_QUIET=1
278 unset GIT_QUIET
280 --progress)
281 progress=1
283 -i|--init)
284 init=1
286 --require-init)
287 init=1
288 require_init=1
290 --remote)
291 remote=1
293 -N|--no-fetch)
294 nofetch=1
296 -f|--force)
297 force=$1
299 -r|--rebase)
300 update="rebase"
302 --reference)
303 case "$2" in '') usage ;; esac
304 reference="--reference=$2"
305 shift
307 --reference=*)
308 reference="$1"
310 --dissociate)
311 dissociate=1
313 -m|--merge)
314 update="merge"
316 --recursive)
317 recursive=1
319 --checkout)
320 update="checkout"
322 --recommend-shallow)
323 recommend_shallow="--recommend-shallow"
325 --no-recommend-shallow)
326 recommend_shallow="--no-recommend-shallow"
328 --depth)
329 case "$2" in '') usage ;; esac
330 depth="--depth=$2"
331 shift
333 --depth=*)
334 depth=$1
336 -j|--jobs)
337 case "$2" in '') usage ;; esac
338 jobs="--jobs=$2"
339 shift
341 --jobs=*)
342 jobs=$1
344 --single-branch)
345 single_branch="--single-branch"
347 --no-single-branch)
348 single_branch="--no-single-branch"
351 shift
352 break
355 usage
358 break
360 esac
361 shift
362 done
364 if test -n "$init"
365 then
366 cmd_init "--" "$@" || return
370 git submodule--helper update-clone ${GIT_QUIET:+--quiet} \
371 ${progress:+"--progress"} \
372 ${wt_prefix:+--prefix "$wt_prefix"} \
373 ${prefix:+--recursive-prefix "$prefix"} \
374 ${update:+--update "$update"} \
375 ${reference:+"$reference"} \
376 ${dissociate:+"--dissociate"} \
377 ${depth:+--depth "$depth"} \
378 ${require_init:+--require-init} \
379 $single_branch \
380 $recommend_shallow \
381 $jobs \
382 -- \
383 "$@" || echo "#unmatched" $?
384 } | {
385 err=
386 while read -r quickabort sha1 just_cloned sm_path
388 die_if_unmatched "$quickabort" "$sha1"
390 git submodule--helper ensure-core-worktree "$sm_path" || exit 1
392 displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
394 if test $just_cloned -eq 1
395 then
396 subsha1=
397 else
398 just_cloned=
399 subsha1=$(sanitize_submodule_env; cd "$sm_path" &&
400 git rev-parse --verify HEAD) ||
401 die "fatal: $(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
404 if test -n "$remote"
405 then
406 branch=$(git submodule--helper remote-branch "$sm_path")
407 if test -z "$nofetch"
408 then
409 # Fetch remote before determining tracking $sha1
410 fetch_in_submodule "$sm_path" $depth ||
411 die "fatal: $(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
413 remote_name=$(sanitize_submodule_env; cd "$sm_path" && git submodule--helper print-default-remote)
414 sha1=$(sanitize_submodule_env; cd "$sm_path" &&
415 git rev-parse --verify "${remote_name}/${branch}") ||
416 die "fatal: $(eval_gettext "Unable to find current \${remote_name}/\${branch} revision in submodule path '\$sm_path'")"
419 out=$(git submodule--helper run-update-procedure \
420 ${wt_prefix:+--prefix "$wt_prefix"} \
421 ${GIT_QUIET:+--quiet} \
422 ${force:+--force} \
423 ${just_cloned:+--just-cloned} \
424 ${nofetch:+--no-fetch} \
425 ${depth:+"$depth"} \
426 ${update:+--update "$update"} \
427 ${prefix:+--recursive-prefix "$prefix"} \
428 ${sha1:+--oid "$sha1"} \
429 ${subsha1:+--suboid "$subsha1"} \
430 "--" \
431 "$sm_path")
433 # exit codes for run-update-procedure:
434 # 0: update was successful, say command output
435 # 1: update procedure failed, but should not die
436 # 2 or 128: subcommand died during execution
437 # 3: no update procedure was run
438 res="$?"
439 case $res in
441 say "$out"
444 err="${err};fatal: $out"
445 continue
447 2|128)
448 die_with_status $res "fatal: $out"
450 esac
452 if test -n "$recursive"
453 then
455 prefix=$(git submodule--helper relative-path "$prefix$sm_path/" "$wt_prefix")
456 wt_prefix=
457 sanitize_submodule_env
458 cd "$sm_path" &&
459 eval cmd_update
461 res=$?
462 if test $res -gt 0
463 then
464 die_msg="fatal: $(eval_gettext "Failed to recurse into submodule path '\$displaypath'")"
465 if test $res -ne 2
466 then
467 err="${err};$die_msg"
468 continue
469 else
470 die_with_status $res "$die_msg"
474 done
476 if test -n "$err"
477 then
478 OIFS=$IFS
479 IFS=';'
480 for e in $err
482 if test -n "$e"
483 then
484 echo >&2 "$e"
486 done
487 IFS=$OIFS
488 exit 1
494 # Configures a submodule's default branch
496 # $@ = requested path
498 cmd_set_branch() {
499 default=
500 branch=
502 while test $# -ne 0
504 case "$1" in
505 -q|--quiet)
506 # we don't do anything with this but we need to accept it
508 -d|--default)
509 default=1
511 -b|--branch)
512 case "$2" in '') usage ;; esac
513 branch=$2
514 shift
517 shift
518 break
521 usage
524 break
526 esac
527 shift
528 done
530 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-branch ${GIT_QUIET:+--quiet} ${branch:+--branch "$branch"} ${default:+--default} -- "$@"
534 # Configures a submodule's remote url
536 # $@ = requested path, requested url
538 cmd_set_url() {
539 while test $# -ne 0
541 case "$1" in
542 -q|--quiet)
543 GIT_QUIET=1
546 shift
547 break
550 usage
553 break
555 esac
556 shift
557 done
559 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-url ${GIT_QUIET:+--quiet} -- "$@"
563 # Show commit summary for submodules in index or working tree
565 # If '--cached' is given, show summary between index and given commit,
566 # or between working tree and given commit
568 # $@ = [commit (default 'HEAD'),] requested paths (default all)
570 cmd_summary() {
571 summary_limit=-1
572 for_status=
573 diff_cmd=diff-index
575 # parse $args after "submodule ... summary".
576 while test $# -ne 0
578 case "$1" in
579 --cached)
580 cached="$1"
582 --files)
583 files="$1"
585 --for-status)
586 for_status="$1"
588 -n|--summary-limit)
589 summary_limit="$2"
590 isnumber "$summary_limit" || usage
591 shift
593 --summary-limit=*)
594 summary_limit="${1#--summary-limit=}"
595 isnumber "$summary_limit" || usage
598 shift
599 break
602 usage
605 break
607 esac
608 shift
609 done
611 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper summary ${files:+--files} ${cached:+--cached} ${for_status:+--for-status} ${summary_limit:+-n $summary_limit} -- "$@"
614 # List all submodules, prefixed with:
615 # - submodule not initialized
616 # + different revision checked out
618 # If --cached was specified the revision in the index will be printed
619 # instead of the currently checked out revision.
621 # $@ = requested paths (default to all)
623 cmd_status()
625 # parse $args after "submodule ... status".
626 while test $# -ne 0
628 case "$1" in
629 -q|--quiet)
630 GIT_QUIET=1
632 --cached)
633 cached=1
635 --recursive)
636 recursive=1
639 shift
640 break
643 usage
646 break
648 esac
649 shift
650 done
652 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper status ${GIT_QUIET:+--quiet} ${cached:+--cached} ${recursive:+--recursive} -- "$@"
655 # Sync remote urls for submodules
656 # This makes the value for remote.$remote.url match the value
657 # specified in .gitmodules.
659 cmd_sync()
661 while test $# -ne 0
663 case "$1" in
664 -q|--quiet)
665 GIT_QUIET=1
666 shift
668 --recursive)
669 recursive=1
670 shift
673 shift
674 break
677 usage
680 break
682 esac
683 done
685 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper sync ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@"
688 cmd_absorbgitdirs()
690 git submodule--helper absorb-git-dirs --prefix "$wt_prefix" "$@"
693 # This loop parses the command line arguments to find the
694 # subcommand name to dispatch. Parsing of the subcommand specific
695 # options are primarily done by the subcommand implementations.
696 # Subcommand specific options such as --branch and --cached are
697 # parsed here as well, for backward compatibility.
699 while test $# != 0 && test -z "$command"
701 case "$1" in
702 add | foreach | init | deinit | update | set-branch | set-url | status | summary | sync | absorbgitdirs)
703 command=$1
705 -q|--quiet)
706 GIT_QUIET=1
708 -b|--branch)
709 case "$2" in
711 usage
713 esac
714 branch="$2"; shift
716 --cached)
717 cached="$1"
720 break
723 usage
726 break
728 esac
729 shift
730 done
732 # No command word defaults to "status"
733 if test -z "$command"
734 then
735 if test $# = 0
736 then
737 command=status
738 else
739 usage
743 # "-b branch" is accepted only by "add" and "set-branch"
744 if test -n "$branch" && (test "$command" != add || test "$command" != set-branch)
745 then
746 usage
749 # "--cached" is accepted only by "status" and "summary"
750 if test -n "$cached" && test "$command" != status && test "$command" != summary
751 then
752 usage
755 "cmd_$(echo $command | sed -e s/-/_/g)" "$@"