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

/gitweb-b1ab8b5/git-submodule.sh

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