PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/git-submodule.sh

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