PageRenderTime 62ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/git-submodule.sh

https://bitbucket.org/brodie/git
Shell | 998 lines | 826 code | 62 blank | 110 comment | 97 complexity | c34c78f6dc9c11c70171841bcce694e9 MD5 | raw file
Possible License(s): BSD-2-Clause, GPL-2.0, LGPL-2.1
  1. #!/bin/sh
  2. #
  3. # git-submodules.sh: add, init, update or list git submodules
  4. #
  5. # Copyright (c) 2007 Lars Hjemli
  6. dashless=$(basename "$0" | sed -e 's/-/ /')
  7. USAGE="[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <repository> [<path>]
  8. or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
  9. or: $dashless [--quiet] init [--] [<path>...]
  10. or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
  11. or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
  12. or: $dashless [--quiet] foreach [--recursive] <command>
  13. or: $dashless [--quiet] sync [--] [<path>...]"
  14. OPTIONS_SPEC=
  15. . git-sh-setup
  16. . git-sh-i18n
  17. . git-parse-remote
  18. require_work_tree
  19. command=
  20. branch=
  21. force=
  22. reference=
  23. cached=
  24. recursive=
  25. init=
  26. files=
  27. nofetch=
  28. update=
  29. prefix=
  30. # Resolve relative url by appending to parent's url
  31. resolve_relative_url ()
  32. {
  33. remote=$(get_default_remote)
  34. remoteurl=$(git config "remote.$remote.url") ||
  35. remoteurl=$(pwd) # the repository is its own authoritative upstream
  36. url="$1"
  37. remoteurl=${remoteurl%/}
  38. sep=/
  39. while test -n "$url"
  40. do
  41. case "$url" in
  42. ../*)
  43. url="${url#../}"
  44. case "$remoteurl" in
  45. */*)
  46. remoteurl="${remoteurl%/*}"
  47. ;;
  48. *:*)
  49. remoteurl="${remoteurl%:*}"
  50. sep=:
  51. ;;
  52. *)
  53. die "$(eval_gettext "cannot strip one component off url '\$remoteurl'")"
  54. ;;
  55. esac
  56. ;;
  57. ./*)
  58. url="${url#./}"
  59. ;;
  60. *)
  61. break;;
  62. esac
  63. done
  64. echo "$remoteurl$sep${url%/}"
  65. }
  66. #
  67. # Get submodule info for registered submodules
  68. # $@ = path to limit submodule list
  69. #
  70. module_list()
  71. {
  72. git ls-files --error-unmatch --stage -- "$@" |
  73. perl -e '
  74. my %unmerged = ();
  75. my ($null_sha1) = ("0" x 40);
  76. while (<STDIN>) {
  77. chomp;
  78. my ($mode, $sha1, $stage, $path) =
  79. /^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
  80. next unless $mode eq "160000";
  81. if ($stage ne "0") {
  82. if (!$unmerged{$path}++) {
  83. print "$mode $null_sha1 U\t$path\n";
  84. }
  85. next;
  86. }
  87. print "$_\n";
  88. }
  89. '
  90. }
  91. #
  92. # Map submodule path to submodule name
  93. #
  94. # $1 = path
  95. #
  96. module_name()
  97. {
  98. # Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
  99. re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
  100. name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
  101. sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
  102. test -z "$name" &&
  103. die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$path'")"
  104. echo "$name"
  105. }
  106. #
  107. # Clone a submodule
  108. #
  109. # Prior to calling, cmd_update checks that a possibly existing
  110. # path is not a git repository.
  111. # Likewise, cmd_add checks that path does not exist at all,
  112. # since it is the location of a new submodule.
  113. #
  114. module_clone()
  115. {
  116. path=$1
  117. url=$2
  118. reference="$3"
  119. quiet=
  120. if test -n "$GIT_QUIET"
  121. then
  122. quiet=-q
  123. fi
  124. if test -n "$reference"
  125. then
  126. git-clone $quiet "$reference" -n "$url" "$path"
  127. else
  128. git-clone $quiet -n "$url" "$path"
  129. fi ||
  130. die "$(eval_gettext "Clone of '\$url' into submodule path '\$path' failed")"
  131. }
  132. #
  133. # Add a new submodule to the working tree, .gitmodules and the index
  134. #
  135. # $@ = repo path
  136. #
  137. # optional branch is stored in global branch variable
  138. #
  139. cmd_add()
  140. {
  141. # parse $args after "submodule ... add".
  142. while test $# -ne 0
  143. do
  144. case "$1" in
  145. -b | --branch)
  146. case "$2" in '') usage ;; esac
  147. branch=$2
  148. shift
  149. ;;
  150. -f | --force)
  151. force=$1
  152. ;;
  153. -q|--quiet)
  154. GIT_QUIET=1
  155. ;;
  156. --reference)
  157. case "$2" in '') usage ;; esac
  158. reference="--reference=$2"
  159. shift
  160. ;;
  161. --reference=*)
  162. reference="$1"
  163. shift
  164. ;;
  165. --)
  166. shift
  167. break
  168. ;;
  169. -*)
  170. usage
  171. ;;
  172. *)
  173. break
  174. ;;
  175. esac
  176. shift
  177. done
  178. repo=$1
  179. path=$2
  180. if test -z "$path"; then
  181. path=$(echo "$repo" |
  182. sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
  183. fi
  184. if test -z "$repo" -o -z "$path"; then
  185. usage
  186. fi
  187. # assure repo is absolute or relative to parent
  188. case "$repo" in
  189. ./*|../*)
  190. # dereference source url relative to parent's url
  191. realrepo=$(resolve_relative_url "$repo") || exit
  192. ;;
  193. *:*|/*)
  194. # absolute url
  195. realrepo=$repo
  196. ;;
  197. *)
  198. die "$(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
  199. ;;
  200. esac
  201. # normalize path:
  202. # multiple //; leading ./; /./; /../; trailing /
  203. path=$(printf '%s/\n' "$path" |
  204. sed -e '
  205. s|//*|/|g
  206. s|^\(\./\)*||
  207. s|/\./|/|g
  208. :start
  209. s|\([^/]*\)/\.\./||
  210. tstart
  211. s|/*$||
  212. ')
  213. git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
  214. die "$(eval_gettext "'\$path' already exists in the index")"
  215. if test -z "$force" && ! git add --dry-run --ignore-missing "$path" > /dev/null 2>&1
  216. then
  217. (
  218. eval_gettext "The following path is ignored by one of your .gitignore files:
  219. \$path
  220. Use -f if you really want to add it." &&
  221. echo
  222. ) >&2
  223. exit 1
  224. fi
  225. # perhaps the path exists and is already a git repo, else clone it
  226. if test -e "$path"
  227. then
  228. if test -d "$path"/.git -o -f "$path"/.git
  229. then
  230. eval_gettext "Adding existing repo at '\$path' to the index"; echo
  231. else
  232. die "$(eval_gettext "'\$path' already exists and is not a valid git repo")"
  233. fi
  234. else
  235. module_clone "$path" "$realrepo" "$reference" || exit
  236. (
  237. clear_local_git_env
  238. cd "$path" &&
  239. # ash fails to wordsplit ${branch:+-b "$branch"...}
  240. case "$branch" in
  241. '') git checkout -f -q ;;
  242. ?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
  243. esac
  244. ) || die "$(eval_gettext "Unable to checkout submodule '\$path'")"
  245. fi
  246. git config submodule."$path".url "$realrepo"
  247. git add $force "$path" ||
  248. die "$(eval_gettext "Failed to add submodule '\$path'")"
  249. git config -f .gitmodules submodule."$path".path "$path" &&
  250. git config -f .gitmodules submodule."$path".url "$repo" &&
  251. git add --force .gitmodules ||
  252. die "$(eval_gettext "Failed to register submodule '\$path'")"
  253. }
  254. #
  255. # Execute an arbitrary command sequence in each checked out
  256. # submodule
  257. #
  258. # $@ = command to execute
  259. #
  260. cmd_foreach()
  261. {
  262. # parse $args after "submodule ... foreach".
  263. while test $# -ne 0
  264. do
  265. case "$1" in
  266. -q|--quiet)
  267. GIT_QUIET=1
  268. ;;
  269. --recursive)
  270. recursive=1
  271. ;;
  272. -*)
  273. usage
  274. ;;
  275. *)
  276. break
  277. ;;
  278. esac
  279. shift
  280. done
  281. toplevel=$(pwd)
  282. # dup stdin so that it can be restored when running the external
  283. # command in the subshell (and a recursive call to this function)
  284. exec 3<&0
  285. module_list |
  286. while read mode sha1 stage path
  287. do
  288. if test -e "$path"/.git
  289. then
  290. say "$(eval_gettext "Entering '\$prefix\$path'")"
  291. name=$(module_name "$path")
  292. (
  293. prefix="$prefix$path/"
  294. clear_local_git_env
  295. cd "$path" &&
  296. eval "$@" &&
  297. if test -n "$recursive"
  298. then
  299. cmd_foreach "--recursive" "$@"
  300. fi
  301. ) <&3 3<&- ||
  302. die "$(eval_gettext "Stopping at '\$path'; script returned non-zero status.")"
  303. fi
  304. done
  305. }
  306. #
  307. # Register submodules in .git/config
  308. #
  309. # $@ = requested paths (default to all)
  310. #
  311. cmd_init()
  312. {
  313. # parse $args after "submodule ... init".
  314. while test $# -ne 0
  315. do
  316. case "$1" in
  317. -q|--quiet)
  318. GIT_QUIET=1
  319. ;;
  320. --)
  321. shift
  322. break
  323. ;;
  324. -*)
  325. usage
  326. ;;
  327. *)
  328. break
  329. ;;
  330. esac
  331. shift
  332. done
  333. module_list "$@" |
  334. while read mode sha1 stage path
  335. do
  336. # Skip already registered paths
  337. name=$(module_name "$path") || exit
  338. if test -z "$(git config "submodule.$name.url")"
  339. then
  340. url=$(git config -f .gitmodules submodule."$name".url)
  341. test -z "$url" &&
  342. die "$(eval_gettext "No url found for submodule path '\$path' in .gitmodules")"
  343. # Possibly a url relative to parent
  344. case "$url" in
  345. ./*|../*)
  346. url=$(resolve_relative_url "$url") || exit
  347. ;;
  348. esac
  349. git config submodule."$name".url "$url" ||
  350. die "$(eval_gettext "Failed to register url for submodule path '\$path'")"
  351. fi
  352. # Copy "update" setting when it is not set yet
  353. upd="$(git config -f .gitmodules submodule."$name".update)"
  354. test -z "$upd" ||
  355. test -n "$(git config submodule."$name".update)" ||
  356. git config submodule."$name".update "$upd" ||
  357. die "$(eval_gettext "Failed to register update mode for submodule path '\$path'")"
  358. say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$path'")"
  359. done
  360. }
  361. #
  362. # Update each submodule path to correct revision, using clone and checkout as needed
  363. #
  364. # $@ = requested paths (default to all)
  365. #
  366. cmd_update()
  367. {
  368. # parse $args after "submodule ... update".
  369. orig_flags=
  370. while test $# -ne 0
  371. do
  372. case "$1" in
  373. -q|--quiet)
  374. GIT_QUIET=1
  375. ;;
  376. -i|--init)
  377. init=1
  378. ;;
  379. -N|--no-fetch)
  380. nofetch=1
  381. ;;
  382. -f|--force)
  383. force=$1
  384. ;;
  385. -r|--rebase)
  386. update="rebase"
  387. ;;
  388. --reference)
  389. case "$2" in '') usage ;; esac
  390. reference="--reference=$2"
  391. orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
  392. shift
  393. ;;
  394. --reference=*)
  395. reference="$1"
  396. ;;
  397. -m|--merge)
  398. update="merge"
  399. ;;
  400. --recursive)
  401. recursive=1
  402. ;;
  403. --)
  404. shift
  405. break
  406. ;;
  407. -*)
  408. usage
  409. ;;
  410. *)
  411. break
  412. ;;
  413. esac
  414. orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
  415. shift
  416. done
  417. if test -n "$init"
  418. then
  419. cmd_init "--" "$@" || return
  420. fi
  421. cloned_modules=
  422. module_list "$@" | {
  423. err=
  424. while read mode sha1 stage path
  425. do
  426. if test "$stage" = U
  427. then
  428. echo >&2 "Skipping unmerged submodule $path"
  429. continue
  430. fi
  431. name=$(module_name "$path") || exit
  432. url=$(git config submodule."$name".url)
  433. update_module=$(git config submodule."$name".update)
  434. if test -z "$url"
  435. then
  436. # Only mention uninitialized submodules when its
  437. # path have been specified
  438. test "$#" != "0" &&
  439. say "$(eval_gettext "Submodule path '\$path' not initialized
  440. Maybe you want to use 'update --init'?")"
  441. continue
  442. fi
  443. if ! test -d "$path"/.git -o -f "$path"/.git
  444. then
  445. module_clone "$path" "$url" "$reference"|| exit
  446. cloned_modules="$cloned_modules;$name"
  447. subsha1=
  448. else
  449. subsha1=$(clear_local_git_env; cd "$path" &&
  450. git rev-parse --verify HEAD) ||
  451. die "$(eval_gettext "Unable to find current revision in submodule path '\$path'")"
  452. fi
  453. if ! test -z "$update"
  454. then
  455. update_module=$update
  456. fi
  457. if test "$subsha1" != "$sha1"
  458. then
  459. subforce=$force
  460. # If we don't already have a -f flag and the submodule has never been checked out
  461. if test -z "$subsha1" -a -z "$force"
  462. then
  463. subforce="-f"
  464. fi
  465. if test -z "$nofetch"
  466. then
  467. # Run fetch only if $sha1 isn't present or it
  468. # is not reachable from a ref.
  469. (clear_local_git_env; cd "$path" &&
  470. ( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
  471. test -z "$rev") || git-fetch)) ||
  472. die "$(eval_gettext "Unable to fetch in submodule path '\$path'")"
  473. fi
  474. # Is this something we just cloned?
  475. case ";$cloned_modules;" in
  476. *";$name;"*)
  477. # then there is no local change to integrate
  478. update_module= ;;
  479. esac
  480. must_die_on_failure=
  481. case "$update_module" in
  482. rebase)
  483. command="git rebase"
  484. die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$path'")"
  485. say_msg="$(eval_gettext "Submodule path '\$path': rebased into '\$sha1'")"
  486. must_die_on_failure=yes
  487. ;;
  488. merge)
  489. command="git merge"
  490. die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$path'")"
  491. say_msg="$(eval_gettext "Submodule path '\$path': merged in '\$sha1'")"
  492. must_die_on_failure=yes
  493. ;;
  494. *)
  495. command="git checkout $subforce -q"
  496. die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$path'")"
  497. say_msg="$(eval_gettext "Submodule path '\$path': checked out '\$sha1'")"
  498. ;;
  499. esac
  500. if (clear_local_git_env; cd "$path" && $command "$sha1")
  501. then
  502. say "$say_msg"
  503. elif test -n "$must_die_on_failure"
  504. then
  505. die_with_status 2 "$die_msg"
  506. else
  507. err="${err};$die_msg"
  508. continue
  509. fi
  510. fi
  511. if test -n "$recursive"
  512. then
  513. (clear_local_git_env; cd "$path" && eval cmd_update "$orig_flags")
  514. res=$?
  515. if test $res -gt 0
  516. then
  517. die_msg="$(eval_gettext "Failed to recurse into submodule path '\$path'")"
  518. if test $res -eq 1
  519. then
  520. err="${err};$die_msg"
  521. continue
  522. else
  523. die_with_status $res "$die_msg"
  524. fi
  525. fi
  526. fi
  527. done
  528. if test -n "$err"
  529. then
  530. OIFS=$IFS
  531. IFS=';'
  532. for e in $err
  533. do
  534. if test -n "$e"
  535. then
  536. echo >&2 "$e"
  537. fi
  538. done
  539. IFS=$OIFS
  540. exit 1
  541. fi
  542. }
  543. }
  544. set_name_rev () {
  545. revname=$( (
  546. clear_local_git_env
  547. cd "$1" && {
  548. git describe "$2" 2>/dev/null ||
  549. git describe --tags "$2" 2>/dev/null ||
  550. git describe --contains "$2" 2>/dev/null ||
  551. git describe --all --always "$2"
  552. }
  553. ) )
  554. test -z "$revname" || revname=" ($revname)"
  555. }
  556. #
  557. # Show commit summary for submodules in index or working tree
  558. #
  559. # If '--cached' is given, show summary between index and given commit,
  560. # or between working tree and given commit
  561. #
  562. # $@ = [commit (default 'HEAD'),] requested paths (default all)
  563. #
  564. cmd_summary() {
  565. summary_limit=-1
  566. for_status=
  567. diff_cmd=diff-index
  568. # parse $args after "submodule ... summary".
  569. while test $# -ne 0
  570. do
  571. case "$1" in
  572. --cached)
  573. cached="$1"
  574. ;;
  575. --files)
  576. files="$1"
  577. ;;
  578. --for-status)
  579. for_status="$1"
  580. ;;
  581. -n|--summary-limit)
  582. if summary_limit=$(($2 + 0)) 2>/dev/null && test "$summary_limit" = "$2"
  583. then
  584. :
  585. else
  586. usage
  587. fi
  588. shift
  589. ;;
  590. --)
  591. shift
  592. break
  593. ;;
  594. -*)
  595. usage
  596. ;;
  597. *)
  598. break
  599. ;;
  600. esac
  601. shift
  602. done
  603. test $summary_limit = 0 && return
  604. if rev=$(git rev-parse -q --verify --default HEAD ${1+"$1"})
  605. then
  606. head=$rev
  607. test $# = 0 || shift
  608. elif test -z "$1" -o "$1" = "HEAD"
  609. then
  610. # before the first commit: compare with an empty tree
  611. head=$(git hash-object -w -t tree --stdin </dev/null)
  612. test -z "$1" || shift
  613. else
  614. head="HEAD"
  615. fi
  616. if [ -n "$files" ]
  617. then
  618. test -n "$cached" &&
  619. die "$(gettext -- "--cached cannot be used with --files")"
  620. diff_cmd=diff-files
  621. head=
  622. fi
  623. cd_to_toplevel
  624. # Get modified modules cared by user
  625. modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
  626. sane_egrep '^:([0-7]* )?160000' |
  627. while read mod_src mod_dst sha1_src sha1_dst status name
  628. do
  629. # Always show modules deleted or type-changed (blob<->module)
  630. test $status = D -o $status = T && echo "$name" && continue
  631. # Also show added or modified modules which are checked out
  632. GIT_DIR="$name/.git" git-rev-parse --git-dir >/dev/null 2>&1 &&
  633. echo "$name"
  634. done
  635. )
  636. test -z "$modules" && return
  637. git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- $modules |
  638. sane_egrep '^:([0-7]* )?160000' |
  639. cut -c2- |
  640. while read mod_src mod_dst sha1_src sha1_dst status name
  641. do
  642. if test -z "$cached" &&
  643. test $sha1_dst = 0000000000000000000000000000000000000000
  644. then
  645. case "$mod_dst" in
  646. 160000)
  647. sha1_dst=$(GIT_DIR="$name/.git" git rev-parse HEAD)
  648. ;;
  649. 100644 | 100755 | 120000)
  650. sha1_dst=$(git hash-object $name)
  651. ;;
  652. 000000)
  653. ;; # removed
  654. *)
  655. # unexpected type
  656. (
  657. eval_gettext "unexpected mode \$mod_dst" &&
  658. echo
  659. ) >&2
  660. continue ;;
  661. esac
  662. fi
  663. missing_src=
  664. missing_dst=
  665. test $mod_src = 160000 &&
  666. ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_src^0 >/dev/null &&
  667. missing_src=t
  668. test $mod_dst = 160000 &&
  669. ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
  670. missing_dst=t
  671. total_commits=
  672. case "$missing_src,$missing_dst" in
  673. t,)
  674. errmsg="$(eval_gettext " Warn: \$name doesn't contain commit \$sha1_src")"
  675. ;;
  676. ,t)
  677. errmsg="$(eval_gettext " Warn: \$name doesn't contain commit \$sha1_dst")"
  678. ;;
  679. t,t)
  680. errmsg="$(eval_gettext " Warn: \$name doesn't contain commits \$sha1_src and \$sha1_dst")"
  681. ;;
  682. *)
  683. errmsg=
  684. total_commits=$(
  685. if test $mod_src = 160000 -a $mod_dst = 160000
  686. then
  687. range="$sha1_src...$sha1_dst"
  688. elif test $mod_src = 160000
  689. then
  690. range=$sha1_src
  691. else
  692. range=$sha1_dst
  693. fi
  694. GIT_DIR="$name/.git" \
  695. git rev-list --first-parent $range -- | wc -l
  696. )
  697. total_commits=" ($(($total_commits + 0)))"
  698. ;;
  699. esac
  700. sha1_abbr_src=$(echo $sha1_src | cut -c1-7)
  701. sha1_abbr_dst=$(echo $sha1_dst | cut -c1-7)
  702. if test $status = T
  703. then
  704. blob="$(gettext "blob")"
  705. submodule="$(gettext "submodule")"
  706. if test $mod_dst = 160000
  707. then
  708. echo "* $name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
  709. else
  710. echo "* $name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
  711. fi
  712. else
  713. echo "* $name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
  714. fi
  715. if test -n "$errmsg"
  716. then
  717. # Don't give error msg for modification whose dst is not submodule
  718. # i.e. deleted or changed to blob
  719. test $mod_dst = 160000 && echo "$errmsg"
  720. else
  721. if test $mod_src = 160000 -a $mod_dst = 160000
  722. then
  723. limit=
  724. test $summary_limit -gt 0 && limit="-$summary_limit"
  725. GIT_DIR="$name/.git" \
  726. git log $limit --pretty='format: %m %s' \
  727. --first-parent $sha1_src...$sha1_dst
  728. elif test $mod_dst = 160000
  729. then
  730. GIT_DIR="$name/.git" \
  731. git log --pretty='format: > %s' -1 $sha1_dst
  732. else
  733. GIT_DIR="$name/.git" \
  734. git log --pretty='format: < %s' -1 $sha1_src
  735. fi
  736. echo
  737. fi
  738. echo
  739. done |
  740. if test -n "$for_status"; then
  741. if [ -n "$files" ]; then
  742. gettext "# Submodules changed but not updated:"; echo
  743. else
  744. gettext "# Submodule changes to be committed:"; echo
  745. fi
  746. echo "#"
  747. sed -e 's|^|# |' -e 's|^# $|#|'
  748. else
  749. cat
  750. fi
  751. }
  752. #
  753. # List all submodules, prefixed with:
  754. # - submodule not initialized
  755. # + different revision checked out
  756. #
  757. # If --cached was specified the revision in the index will be printed
  758. # instead of the currently checked out revision.
  759. #
  760. # $@ = requested paths (default to all)
  761. #
  762. cmd_status()
  763. {
  764. # parse $args after "submodule ... status".
  765. orig_flags=
  766. while test $# -ne 0
  767. do
  768. case "$1" in
  769. -q|--quiet)
  770. GIT_QUIET=1
  771. ;;
  772. --cached)
  773. cached=1
  774. ;;
  775. --recursive)
  776. recursive=1
  777. ;;
  778. --)
  779. shift
  780. break
  781. ;;
  782. -*)
  783. usage
  784. ;;
  785. *)
  786. break
  787. ;;
  788. esac
  789. orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
  790. shift
  791. done
  792. module_list "$@" |
  793. while read mode sha1 stage path
  794. do
  795. name=$(module_name "$path") || exit
  796. url=$(git config submodule."$name".url)
  797. displaypath="$prefix$path"
  798. if test "$stage" = U
  799. then
  800. say "U$sha1 $displaypath"
  801. continue
  802. fi
  803. if test -z "$url" || ! test -d "$path"/.git -o -f "$path"/.git
  804. then
  805. say "-$sha1 $displaypath"
  806. continue;
  807. fi
  808. set_name_rev "$path" "$sha1"
  809. if git diff-files --ignore-submodules=dirty --quiet -- "$path"
  810. then
  811. say " $sha1 $displaypath$revname"
  812. else
  813. if test -z "$cached"
  814. then
  815. sha1=$(clear_local_git_env; cd "$path" && git rev-parse --verify HEAD)
  816. set_name_rev "$path" "$sha1"
  817. fi
  818. say "+$sha1 $displaypath$revname"
  819. fi
  820. if test -n "$recursive"
  821. then
  822. (
  823. prefix="$displaypath/"
  824. clear_local_git_env
  825. cd "$path" &&
  826. eval cmd_status "$orig_args"
  827. ) ||
  828. die "$(eval_gettext "Failed to recurse into submodule path '\$path'")"
  829. fi
  830. done
  831. }
  832. #
  833. # Sync remote urls for submodules
  834. # This makes the value for remote.$remote.url match the value
  835. # specified in .gitmodules.
  836. #
  837. cmd_sync()
  838. {
  839. while test $# -ne 0
  840. do
  841. case "$1" in
  842. -q|--quiet)
  843. GIT_QUIET=1
  844. shift
  845. ;;
  846. --)
  847. shift
  848. break
  849. ;;
  850. -*)
  851. usage
  852. ;;
  853. *)
  854. break
  855. ;;
  856. esac
  857. done
  858. cd_to_toplevel
  859. module_list "$@" |
  860. while read mode sha1 stage path
  861. do
  862. name=$(module_name "$path")
  863. url=$(git config -f .gitmodules --get submodule."$name".url)
  864. # Possibly a url relative to parent
  865. case "$url" in
  866. ./*|../*)
  867. url=$(resolve_relative_url "$url") || exit
  868. ;;
  869. esac
  870. if git config "submodule.$name.url" >/dev/null 2>/dev/null
  871. then
  872. say "$(eval_gettext "Synchronizing submodule url for '\$name'")"
  873. git config submodule."$name".url "$url"
  874. if test -e "$path"/.git
  875. then
  876. (
  877. clear_local_git_env
  878. cd "$path"
  879. remote=$(get_default_remote)
  880. git config remote."$remote".url "$url"
  881. )
  882. fi
  883. fi
  884. done
  885. }
  886. # This loop parses the command line arguments to find the
  887. # subcommand name to dispatch. Parsing of the subcommand specific
  888. # options are primarily done by the subcommand implementations.
  889. # Subcommand specific options such as --branch and --cached are
  890. # parsed here as well, for backward compatibility.
  891. while test $# != 0 && test -z "$command"
  892. do
  893. case "$1" in
  894. add | foreach | init | update | status | summary | sync)
  895. command=$1
  896. ;;
  897. -q|--quiet)
  898. GIT_QUIET=1
  899. ;;
  900. -b|--branch)
  901. case "$2" in
  902. '')
  903. usage
  904. ;;
  905. esac
  906. branch="$2"; shift
  907. ;;
  908. --cached)
  909. cached="$1"
  910. ;;
  911. --)
  912. break
  913. ;;
  914. -*)
  915. usage
  916. ;;
  917. *)
  918. break
  919. ;;
  920. esac
  921. shift
  922. done
  923. # No command word defaults to "status"
  924. test -n "$command" || command=status
  925. # "-b branch" is accepted only by "add"
  926. if test -n "$branch" && test "$command" != add
  927. then
  928. usage
  929. fi
  930. # "--cached" is accepted only by "status" and "summary"
  931. if test -n "$cached" && test "$command" != status -a "$command" != summary
  932. then
  933. usage
  934. fi
  935. "cmd_$command" "$@"