PageRenderTime 57ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/bin/git-folder/git-submodule

https://bitbucket.org/kendfinger/crostools
Shell | 992 lines | 820 code | 62 blank | 110 comment | 97 complexity | b76b818798f4cbc7cdb9cca28eb42839 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-2-Clause
  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. eval_gettextln "The following path is ignored by one of your .gitignore files:
  218. \$path
  219. Use -f if you really want to add it." >&2
  220. exit 1
  221. fi
  222. # perhaps the path exists and is already a git repo, else clone it
  223. if test -e "$path"
  224. then
  225. if test -d "$path"/.git -o -f "$path"/.git
  226. then
  227. eval_gettextln "Adding existing repo at '\$path' to the index"
  228. else
  229. die "$(eval_gettext "'\$path' already exists and is not a valid git repo")"
  230. fi
  231. else
  232. module_clone "$path" "$realrepo" "$reference" || exit
  233. (
  234. clear_local_git_env
  235. cd "$path" &&
  236. # ash fails to wordsplit ${branch:+-b "$branch"...}
  237. case "$branch" in
  238. '') git checkout -f -q ;;
  239. ?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
  240. esac
  241. ) || die "$(eval_gettext "Unable to checkout submodule '\$path'")"
  242. fi
  243. git config submodule."$path".url "$realrepo"
  244. git add $force "$path" ||
  245. die "$(eval_gettext "Failed to add submodule '\$path'")"
  246. git config -f .gitmodules submodule."$path".path "$path" &&
  247. git config -f .gitmodules submodule."$path".url "$repo" &&
  248. git add --force .gitmodules ||
  249. die "$(eval_gettext "Failed to register submodule '\$path'")"
  250. }
  251. #
  252. # Execute an arbitrary command sequence in each checked out
  253. # submodule
  254. #
  255. # $@ = command to execute
  256. #
  257. cmd_foreach()
  258. {
  259. # parse $args after "submodule ... foreach".
  260. while test $# -ne 0
  261. do
  262. case "$1" in
  263. -q|--quiet)
  264. GIT_QUIET=1
  265. ;;
  266. --recursive)
  267. recursive=1
  268. ;;
  269. -*)
  270. usage
  271. ;;
  272. *)
  273. break
  274. ;;
  275. esac
  276. shift
  277. done
  278. toplevel=$(pwd)
  279. # dup stdin so that it can be restored when running the external
  280. # command in the subshell (and a recursive call to this function)
  281. exec 3<&0
  282. module_list |
  283. while read mode sha1 stage path
  284. do
  285. if test -e "$path"/.git
  286. then
  287. say "$(eval_gettext "Entering '\$prefix\$path'")"
  288. name=$(module_name "$path")
  289. (
  290. prefix="$prefix$path/"
  291. clear_local_git_env
  292. cd "$path" &&
  293. eval "$@" &&
  294. if test -n "$recursive"
  295. then
  296. cmd_foreach "--recursive" "$@"
  297. fi
  298. ) <&3 3<&- ||
  299. die "$(eval_gettext "Stopping at '\$path'; script returned non-zero status.")"
  300. fi
  301. done
  302. }
  303. #
  304. # Register submodules in .git/config
  305. #
  306. # $@ = requested paths (default to all)
  307. #
  308. cmd_init()
  309. {
  310. # parse $args after "submodule ... init".
  311. while test $# -ne 0
  312. do
  313. case "$1" in
  314. -q|--quiet)
  315. GIT_QUIET=1
  316. ;;
  317. --)
  318. shift
  319. break
  320. ;;
  321. -*)
  322. usage
  323. ;;
  324. *)
  325. break
  326. ;;
  327. esac
  328. shift
  329. done
  330. module_list "$@" |
  331. while read mode sha1 stage path
  332. do
  333. # Skip already registered paths
  334. name=$(module_name "$path") || exit
  335. if test -z "$(git config "submodule.$name.url")"
  336. then
  337. url=$(git config -f .gitmodules submodule."$name".url)
  338. test -z "$url" &&
  339. die "$(eval_gettext "No url found for submodule path '\$path' in .gitmodules")"
  340. # Possibly a url relative to parent
  341. case "$url" in
  342. ./*|../*)
  343. url=$(resolve_relative_url "$url") || exit
  344. ;;
  345. esac
  346. git config submodule."$name".url "$url" ||
  347. die "$(eval_gettext "Failed to register url for submodule path '\$path'")"
  348. fi
  349. # Copy "update" setting when it is not set yet
  350. upd="$(git config -f .gitmodules submodule."$name".update)"
  351. test -z "$upd" ||
  352. test -n "$(git config submodule."$name".update)" ||
  353. git config submodule."$name".update "$upd" ||
  354. die "$(eval_gettext "Failed to register update mode for submodule path '\$path'")"
  355. say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$path'")"
  356. done
  357. }
  358. #
  359. # Update each submodule path to correct revision, using clone and checkout as needed
  360. #
  361. # $@ = requested paths (default to all)
  362. #
  363. cmd_update()
  364. {
  365. # parse $args after "submodule ... update".
  366. orig_flags=
  367. while test $# -ne 0
  368. do
  369. case "$1" in
  370. -q|--quiet)
  371. GIT_QUIET=1
  372. ;;
  373. -i|--init)
  374. init=1
  375. ;;
  376. -N|--no-fetch)
  377. nofetch=1
  378. ;;
  379. -f|--force)
  380. force=$1
  381. ;;
  382. -r|--rebase)
  383. update="rebase"
  384. ;;
  385. --reference)
  386. case "$2" in '') usage ;; esac
  387. reference="--reference=$2"
  388. orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
  389. shift
  390. ;;
  391. --reference=*)
  392. reference="$1"
  393. ;;
  394. -m|--merge)
  395. update="merge"
  396. ;;
  397. --recursive)
  398. recursive=1
  399. ;;
  400. --)
  401. shift
  402. break
  403. ;;
  404. -*)
  405. usage
  406. ;;
  407. *)
  408. break
  409. ;;
  410. esac
  411. orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
  412. shift
  413. done
  414. if test -n "$init"
  415. then
  416. cmd_init "--" "$@" || return
  417. fi
  418. cloned_modules=
  419. module_list "$@" | {
  420. err=
  421. while read mode sha1 stage path
  422. do
  423. if test "$stage" = U
  424. then
  425. echo >&2 "Skipping unmerged submodule $path"
  426. continue
  427. fi
  428. name=$(module_name "$path") || exit
  429. url=$(git config submodule."$name".url)
  430. update_module=$(git config submodule."$name".update)
  431. if test -z "$url"
  432. then
  433. # Only mention uninitialized submodules when its
  434. # path have been specified
  435. test "$#" != "0" &&
  436. say "$(eval_gettext "Submodule path '\$path' not initialized
  437. Maybe you want to use 'update --init'?")"
  438. continue
  439. fi
  440. if ! test -d "$path"/.git -o -f "$path"/.git
  441. then
  442. module_clone "$path" "$url" "$reference"|| exit
  443. cloned_modules="$cloned_modules;$name"
  444. subsha1=
  445. else
  446. subsha1=$(clear_local_git_env; cd "$path" &&
  447. git rev-parse --verify HEAD) ||
  448. die "$(eval_gettext "Unable to find current revision in submodule path '\$path'")"
  449. fi
  450. if ! test -z "$update"
  451. then
  452. update_module=$update
  453. fi
  454. if test "$subsha1" != "$sha1"
  455. then
  456. subforce=$force
  457. # If we don't already have a -f flag and the submodule has never been checked out
  458. if test -z "$subsha1" -a -z "$force"
  459. then
  460. subforce="-f"
  461. fi
  462. if test -z "$nofetch"
  463. then
  464. # Run fetch only if $sha1 isn't present or it
  465. # is not reachable from a ref.
  466. (clear_local_git_env; cd "$path" &&
  467. ( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
  468. test -z "$rev") || git-fetch)) ||
  469. die "$(eval_gettext "Unable to fetch in submodule path '\$path'")"
  470. fi
  471. # Is this something we just cloned?
  472. case ";$cloned_modules;" in
  473. *";$name;"*)
  474. # then there is no local change to integrate
  475. update_module= ;;
  476. esac
  477. must_die_on_failure=
  478. case "$update_module" in
  479. rebase)
  480. command="git rebase"
  481. die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$path'")"
  482. say_msg="$(eval_gettext "Submodule path '\$path': rebased into '\$sha1'")"
  483. must_die_on_failure=yes
  484. ;;
  485. merge)
  486. command="git merge"
  487. die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$path'")"
  488. say_msg="$(eval_gettext "Submodule path '\$path': merged in '\$sha1'")"
  489. must_die_on_failure=yes
  490. ;;
  491. *)
  492. command="git checkout $subforce -q"
  493. die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$path'")"
  494. say_msg="$(eval_gettext "Submodule path '\$path': checked out '\$sha1'")"
  495. ;;
  496. esac
  497. if (clear_local_git_env; cd "$path" && $command "$sha1")
  498. then
  499. say "$say_msg"
  500. elif test -n "$must_die_on_failure"
  501. then
  502. die_with_status 2 "$die_msg"
  503. else
  504. err="${err};$die_msg"
  505. continue
  506. fi
  507. fi
  508. if test -n "$recursive"
  509. then
  510. (clear_local_git_env; cd "$path" && eval cmd_update "$orig_flags")
  511. res=$?
  512. if test $res -gt 0
  513. then
  514. die_msg="$(eval_gettext "Failed to recurse into submodule path '\$path'")"
  515. if test $res -eq 1
  516. then
  517. err="${err};$die_msg"
  518. continue
  519. else
  520. die_with_status $res "$die_msg"
  521. fi
  522. fi
  523. fi
  524. done
  525. if test -n "$err"
  526. then
  527. OIFS=$IFS
  528. IFS=';'
  529. for e in $err
  530. do
  531. if test -n "$e"
  532. then
  533. echo >&2 "$e"
  534. fi
  535. done
  536. IFS=$OIFS
  537. exit 1
  538. fi
  539. }
  540. }
  541. set_name_rev () {
  542. revname=$( (
  543. clear_local_git_env
  544. cd "$1" && {
  545. git describe "$2" 2>/dev/null ||
  546. git describe --tags "$2" 2>/dev/null ||
  547. git describe --contains "$2" 2>/dev/null ||
  548. git describe --all --always "$2"
  549. }
  550. ) )
  551. test -z "$revname" || revname=" ($revname)"
  552. }
  553. #
  554. # Show commit summary for submodules in index or working tree
  555. #
  556. # If '--cached' is given, show summary between index and given commit,
  557. # or between working tree and given commit
  558. #
  559. # $@ = [commit (default 'HEAD'),] requested paths (default all)
  560. #
  561. cmd_summary() {
  562. summary_limit=-1
  563. for_status=
  564. diff_cmd=diff-index
  565. # parse $args after "submodule ... summary".
  566. while test $# -ne 0
  567. do
  568. case "$1" in
  569. --cached)
  570. cached="$1"
  571. ;;
  572. --files)
  573. files="$1"
  574. ;;
  575. --for-status)
  576. for_status="$1"
  577. ;;
  578. -n|--summary-limit)
  579. if summary_limit=$(($2 + 0)) 2>/dev/null && test "$summary_limit" = "$2"
  580. then
  581. :
  582. else
  583. usage
  584. fi
  585. shift
  586. ;;
  587. --)
  588. shift
  589. break
  590. ;;
  591. -*)
  592. usage
  593. ;;
  594. *)
  595. break
  596. ;;
  597. esac
  598. shift
  599. done
  600. test $summary_limit = 0 && return
  601. if rev=$(git rev-parse -q --verify --default HEAD ${1+"$1"})
  602. then
  603. head=$rev
  604. test $# = 0 || shift
  605. elif test -z "$1" -o "$1" = "HEAD"
  606. then
  607. # before the first commit: compare with an empty tree
  608. head=$(git hash-object -w -t tree --stdin </dev/null)
  609. test -z "$1" || shift
  610. else
  611. head="HEAD"
  612. fi
  613. if [ -n "$files" ]
  614. then
  615. test -n "$cached" &&
  616. die "$(gettext -- "--cached cannot be used with --files")"
  617. diff_cmd=diff-files
  618. head=
  619. fi
  620. cd_to_toplevel
  621. # Get modified modules cared by user
  622. modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
  623. sane_egrep '^:([0-7]* )?160000' |
  624. while read mod_src mod_dst sha1_src sha1_dst status name
  625. do
  626. # Always show modules deleted or type-changed (blob<->module)
  627. test $status = D -o $status = T && echo "$name" && continue
  628. # Also show added or modified modules which are checked out
  629. GIT_DIR="$name/.git" git-rev-parse --git-dir >/dev/null 2>&1 &&
  630. echo "$name"
  631. done
  632. )
  633. test -z "$modules" && return
  634. git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- $modules |
  635. sane_egrep '^:([0-7]* )?160000' |
  636. cut -c2- |
  637. while read mod_src mod_dst sha1_src sha1_dst status name
  638. do
  639. if test -z "$cached" &&
  640. test $sha1_dst = 0000000000000000000000000000000000000000
  641. then
  642. case "$mod_dst" in
  643. 160000)
  644. sha1_dst=$(GIT_DIR="$name/.git" git rev-parse HEAD)
  645. ;;
  646. 100644 | 100755 | 120000)
  647. sha1_dst=$(git hash-object $name)
  648. ;;
  649. 000000)
  650. ;; # removed
  651. *)
  652. # unexpected type
  653. eval_gettextln "unexpected mode \$mod_dst" >&2
  654. continue ;;
  655. esac
  656. fi
  657. missing_src=
  658. missing_dst=
  659. test $mod_src = 160000 &&
  660. ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_src^0 >/dev/null &&
  661. missing_src=t
  662. test $mod_dst = 160000 &&
  663. ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
  664. missing_dst=t
  665. total_commits=
  666. case "$missing_src,$missing_dst" in
  667. t,)
  668. errmsg="$(eval_gettext " Warn: \$name doesn't contain commit \$sha1_src")"
  669. ;;
  670. ,t)
  671. errmsg="$(eval_gettext " Warn: \$name doesn't contain commit \$sha1_dst")"
  672. ;;
  673. t,t)
  674. errmsg="$(eval_gettext " Warn: \$name doesn't contain commits \$sha1_src and \$sha1_dst")"
  675. ;;
  676. *)
  677. errmsg=
  678. total_commits=$(
  679. if test $mod_src = 160000 -a $mod_dst = 160000
  680. then
  681. range="$sha1_src...$sha1_dst"
  682. elif test $mod_src = 160000
  683. then
  684. range=$sha1_src
  685. else
  686. range=$sha1_dst
  687. fi
  688. GIT_DIR="$name/.git" \
  689. git rev-list --first-parent $range -- | wc -l
  690. )
  691. total_commits=" ($(($total_commits + 0)))"
  692. ;;
  693. esac
  694. sha1_abbr_src=$(echo $sha1_src | cut -c1-7)
  695. sha1_abbr_dst=$(echo $sha1_dst | cut -c1-7)
  696. if test $status = T
  697. then
  698. blob="$(gettext "blob")"
  699. submodule="$(gettext "submodule")"
  700. if test $mod_dst = 160000
  701. then
  702. echo "* $name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
  703. else
  704. echo "* $name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
  705. fi
  706. else
  707. echo "* $name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
  708. fi
  709. if test -n "$errmsg"
  710. then
  711. # Don't give error msg for modification whose dst is not submodule
  712. # i.e. deleted or changed to blob
  713. test $mod_dst = 160000 && echo "$errmsg"
  714. else
  715. if test $mod_src = 160000 -a $mod_dst = 160000
  716. then
  717. limit=
  718. test $summary_limit -gt 0 && limit="-$summary_limit"
  719. GIT_DIR="$name/.git" \
  720. git log $limit --pretty='format: %m %s' \
  721. --first-parent $sha1_src...$sha1_dst
  722. elif test $mod_dst = 160000
  723. then
  724. GIT_DIR="$name/.git" \
  725. git log --pretty='format: > %s' -1 $sha1_dst
  726. else
  727. GIT_DIR="$name/.git" \
  728. git log --pretty='format: < %s' -1 $sha1_src
  729. fi
  730. echo
  731. fi
  732. echo
  733. done |
  734. if test -n "$for_status"; then
  735. if [ -n "$files" ]; then
  736. gettextln "# Submodules changed but not updated:"
  737. else
  738. gettextln "# Submodule changes to be committed:"
  739. fi
  740. echo "#"
  741. sed -e 's|^|# |' -e 's|^# $|#|'
  742. else
  743. cat
  744. fi
  745. }
  746. #
  747. # List all submodules, prefixed with:
  748. # - submodule not initialized
  749. # + different revision checked out
  750. #
  751. # If --cached was specified the revision in the index will be printed
  752. # instead of the currently checked out revision.
  753. #
  754. # $@ = requested paths (default to all)
  755. #
  756. cmd_status()
  757. {
  758. # parse $args after "submodule ... status".
  759. orig_flags=
  760. while test $# -ne 0
  761. do
  762. case "$1" in
  763. -q|--quiet)
  764. GIT_QUIET=1
  765. ;;
  766. --cached)
  767. cached=1
  768. ;;
  769. --recursive)
  770. recursive=1
  771. ;;
  772. --)
  773. shift
  774. break
  775. ;;
  776. -*)
  777. usage
  778. ;;
  779. *)
  780. break
  781. ;;
  782. esac
  783. orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
  784. shift
  785. done
  786. module_list "$@" |
  787. while read mode sha1 stage path
  788. do
  789. name=$(module_name "$path") || exit
  790. url=$(git config submodule."$name".url)
  791. displaypath="$prefix$path"
  792. if test "$stage" = U
  793. then
  794. say "U$sha1 $displaypath"
  795. continue
  796. fi
  797. if test -z "$url" || ! test -d "$path"/.git -o -f "$path"/.git
  798. then
  799. say "-$sha1 $displaypath"
  800. continue;
  801. fi
  802. set_name_rev "$path" "$sha1"
  803. if git diff-files --ignore-submodules=dirty --quiet -- "$path"
  804. then
  805. say " $sha1 $displaypath$revname"
  806. else
  807. if test -z "$cached"
  808. then
  809. sha1=$(clear_local_git_env; cd "$path" && git rev-parse --verify HEAD)
  810. set_name_rev "$path" "$sha1"
  811. fi
  812. say "+$sha1 $displaypath$revname"
  813. fi
  814. if test -n "$recursive"
  815. then
  816. (
  817. prefix="$displaypath/"
  818. clear_local_git_env
  819. cd "$path" &&
  820. eval cmd_status "$orig_args"
  821. ) ||
  822. die "$(eval_gettext "Failed to recurse into submodule path '\$path'")"
  823. fi
  824. done
  825. }
  826. #
  827. # Sync remote urls for submodules
  828. # This makes the value for remote.$remote.url match the value
  829. # specified in .gitmodules.
  830. #
  831. cmd_sync()
  832. {
  833. while test $# -ne 0
  834. do
  835. case "$1" in
  836. -q|--quiet)
  837. GIT_QUIET=1
  838. shift
  839. ;;
  840. --)
  841. shift
  842. break
  843. ;;
  844. -*)
  845. usage
  846. ;;
  847. *)
  848. break
  849. ;;
  850. esac
  851. done
  852. cd_to_toplevel
  853. module_list "$@" |
  854. while read mode sha1 stage path
  855. do
  856. name=$(module_name "$path")
  857. url=$(git config -f .gitmodules --get submodule."$name".url)
  858. # Possibly a url relative to parent
  859. case "$url" in
  860. ./*|../*)
  861. url=$(resolve_relative_url "$url") || exit
  862. ;;
  863. esac
  864. if git config "submodule.$name.url" >/dev/null 2>/dev/null
  865. then
  866. say "$(eval_gettext "Synchronizing submodule url for '\$name'")"
  867. git config submodule."$name".url "$url"
  868. if test -e "$path"/.git
  869. then
  870. (
  871. clear_local_git_env
  872. cd "$path"
  873. remote=$(get_default_remote)
  874. git config remote."$remote".url "$url"
  875. )
  876. fi
  877. fi
  878. done
  879. }
  880. # This loop parses the command line arguments to find the
  881. # subcommand name to dispatch. Parsing of the subcommand specific
  882. # options are primarily done by the subcommand implementations.
  883. # Subcommand specific options such as --branch and --cached are
  884. # parsed here as well, for backward compatibility.
  885. while test $# != 0 && test -z "$command"
  886. do
  887. case "$1" in
  888. add | foreach | init | update | status | summary | sync)
  889. command=$1
  890. ;;
  891. -q|--quiet)
  892. GIT_QUIET=1
  893. ;;
  894. -b|--branch)
  895. case "$2" in
  896. '')
  897. usage
  898. ;;
  899. esac
  900. branch="$2"; shift
  901. ;;
  902. --cached)
  903. cached="$1"
  904. ;;
  905. --)
  906. break
  907. ;;
  908. -*)
  909. usage
  910. ;;
  911. *)
  912. break
  913. ;;
  914. esac
  915. shift
  916. done
  917. # No command word defaults to "status"
  918. test -n "$command" || command=status
  919. # "-b branch" is accepted only by "add"
  920. if test -n "$branch" && test "$command" != add
  921. then
  922. usage
  923. fi
  924. # "--cached" is accepted only by "status" and "summary"
  925. if test -n "$cached" && test "$command" != status -a "$command" != summary
  926. then
  927. usage
  928. fi
  929. "cmd_$command" "$@"