- Most of the changes are taken from helmo’s repository from following URL: https://github.com/helmo/git-subtree/blob/master/git-subtree.sh - Add code to create a file named .gittrees which can store information on the subtree that is getting merged to the super-repository. The advantage is ‘subtree push’ and ‘subtree pull’ subcommands can be called with only the —prefix option and no need to provide remote url - Add tests for new feature additions. All existing and new tests pass successfully Files changed in this commit: 1. git/contrib/subtree/git-subtree.sh 2. git/contrib/subtree/t/t7900-subtree.sh Signed-off-by: Keval Patel <kapatel@xxxxxxxxxx> --- A selection of updates to git-subtree were offered to the list by couple of people ($gmane/196667) by Herman van Rink and ($gmane/217820) by Paul Campbell For various reasons the work stalled and I would like to pick it up from there The following patches take a selection of these commits and rebase them against the tip of master. The make test works and I have added more tests to cover the new commands and use of .gittrees file for storing the subtree metadata Thanks-to and Based-on-patch-by: - Herman van Rink - Matt Hoffman - Michael Hart - Nate Jones - Paul Campbell - Paul Cartwright - Peter Jaros - bibendi contrib/subtree/git-subtree.sh | 98 +++++++++++++++++++++------------ contrib/subtree/t/t7900-subtree.sh | 106 ++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 36 deletions(-) diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh index db925ca..7d01b4b 100755 --- a/contrib/subtree/git-subtree.sh +++ b/contrib/subtree/git-subtree.sh @@ -8,8 +8,7 @@ if [ $# -eq 0 ]; then set -- -h fi OPTS_SPEC="\ -git subtree add --prefix=<prefix> <commit> -git subtree add --prefix=<prefix> <repository> <ref> +git subtree add --prefix=<prefix> <repository> <refspec> git subtree merge --prefix=<prefix> <commit> git subtree pull --prefix=<prefix> <repository> <ref> git subtree push --prefix=<prefix> <repository> <ref> @@ -490,12 +489,6 @@ ensure_clean() fi } -ensure_valid_ref_format() -{ - git check-ref-format "refs/heads/$1" || - die "'$1' does not look like a ref" -} - cmd_add() { if [ -e "$dir" ]; then @@ -505,22 +498,12 @@ cmd_add() ensure_clean if [ $# -eq 1 ]; then - git rev-parse -q --verify "$1^{commit}" >/dev/null || - die "'$1' does not refer to a commit" - - "cmd_add_commit" "$@" + "cmd_add_commit" "$@" elif [ $# -eq 2 ]; then - # Technically we could accept a refspec here but we're - # just going to turn around and add FETCH_HEAD under the - # specified directory. Allowing a refspec might be - # misleading because we won't do anything with any other - # branches fetched via the refspec. - ensure_valid_ref_format "$2" - - "cmd_add_repository" "$@" + "cmd_add_repository" "$@" else - say "error: parameters were '$@'" - die "Provide either a commit or a repository and commit." + say "error: parameters were '$@'" + die "Provide either a refspec or a repository and refspec." fi } @@ -533,6 +516,24 @@ cmd_add_repository() revs=FETCH_HEAD set -- $revs cmd_add_commit "$@" + + revs=$(git rev-parse $default --revs-only "$@") || exit $? + set -- $revs + rev="$1" + + subtree_mainline_merge=$(git rev-parse HEAD) || exit $? + + # now add it to our list of repos + git config -f .gittrees --unset subtree.$dir.url + git config -f .gittrees --add subtree.$dir.url $repository + git config -f .gittrees --unset subtree.$dir.path + git config -f .gittrees --add subtree.$dir.path $dir + git config -f .gittrees --unset subtree.$dir.branch + git config -f .gittrees --add subtree.$dir.branch $refspec + git config -f .gittrees --unset subtree.$dir.subtreeCommit + git config -f .gittrees --add subtree.$dir.subtreeCommit $rev + git config -f .gittrees --unset subtree.$dir.subtreeMergeCommit + git config -f .gittrees --add subtree.$dir.subtreeMergeCommit $subtree_mainline_merge } cmd_add_commit() @@ -598,7 +599,7 @@ cmd_split() eval "$grl" | while read rev parents; do revcount=$(($revcount + 1)) - say -n "$revcount/$revmax ($createcount) " + say -n "$revcount/$revmax ($createcount)" debug "Processing commit: $rev" exists=$(cache_get $rev) if [ -n "$exists" ]; then @@ -705,31 +706,56 @@ cmd_merge() cmd_pull() { - if [ $# -ne 2 ]; then - die "You must provide <repository> <ref>" + if [ $# -gt 2 ]; then + die "You should provide either <refspec> or <repository> <refspec>" fi + if [ -e "$dir" ]; then ensure_clean - ensure_valid_ref_format "$2" - git fetch "$@" || exit $? + if [ $# -eq 1 ]; then + repository=$(git config -f .gittrees subtree.$prefix.url) + refspec=$1 + elif [ $# -eq 2 ]; then + repository=$1 + refspec=$2 + else + repository=$(git config -f .gittrees subtree.$prefix.url) + refspec=$(git config -f .gittrees subtree.$prefix.branch) + fi + git fetch $repository $refspec || exit $? + echo "git fetch using: " $repository $refspec revs=FETCH_HEAD set -- $revs cmd_merge "$@" + else + die "'$dir' must already exist. Try 'git subtree add'." + fi } cmd_push() { - if [ $# -ne 2 ]; then - die "You must provide <repository> <ref>" + if [ $# -gt 2 ]; then + die "You should provide either <refspec> or <repository> <refspec>" fi - ensure_valid_ref_format "$2" if [ -e "$dir" ]; then - repository=$1 - refspec=$2 - echo "git push using: " $repository $refspec - localrev=$(git subtree split --prefix="$prefix") || die - git push $repository $localrev:refs/heads/$refspec + if [ $# -eq 1 ]; then + repository=$(git config -f .gittrees subtree.$prefix.url) + refspec=$1 + elif [ $# -eq 2 ]; then + repository=$1 + refspec=$2 + else + repository=$(git config -f .gittrees subtree.$prefix.url) + refspec=$(git config -f .gittrees subtree.$prefix.branch) + fi + echo "git push using: " $repository $refspec + rev=$(git subtree split --prefix=$prefix) + if [ -n "$rev" ]; then + git push $repository $rev:refs/heads/$refspec + else + die "Couldn't push, 'git subtree split' failed." + fi else - die "'$dir' must already exist. Try 'git subtree add'." + die "'$dir' must already exist. Try 'git subtree add'." fi } diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index 66ce4b0..05110f7 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -60,6 +60,11 @@ last_commit_message() git log --pretty=format:%s -1 } +last_commit_id() +{ + git log --format="%H" -n 1 +} + test_expect_success 'init subproj' ' test_create_repo subproj ' @@ -464,5 +469,106 @@ test_expect_success 'verify one file change per commit' ' check_equal "$x" 1 )) ' +# Tests for subtree add which creates .gittrees for storing metadata + +# Back to mainline and create new directory for testing +cd ../.. + +mkdir test_sub +cd test_sub + +mkdir shared_projects +# To shared_projects! +cd shared_projects + +# Create couple of Git repos in shared_projects folder which can be +# added as subtrees to our parent projects +test_expect_success 'add subtree1' ' + test_create_repo subtree1 && + cd subtree1 && + create sub1_file1 && + git commit -m "Initial subtree1 commit" +' + +# Store the latest commit value for future use +expected_subtreeCommit=`echo $(last_commit_id)` +expected_branch=`echo $(git rev-parse --abbrev-ref HEAD)` + +# Back to shared_projects +cd .. + +test_expect_success 'add subtree2' ' + test_create_repo subtree2 && + cd subtree2 && + create sub2_file1 && + git commit -m "Initial subtree2 commit" +' + +# Back to test_sub +cd ../.. + +# Create test parent repos that will add subtrees to itself +test_expect_success 'add parent1' ' + test_create_repo parent1 && + cd parent1 && + create parent1_file1 && + git commit -m "Initial parent1 commit" +' + +# Back to test_sub from parent1 +cd .. + +test_expect_success 'add parent2' ' + test_create_repo parent2 && + cd parent2 && + create parent2_file1 && + git commit -m "Initial parent2 commit" +' + + +# To parent1 now. Start the tests +cd ../parent1 + +# .gittrees file creation tests +test_expect_success 'check add for subtree with master branch' ' + git subtree add -m "Add sub1 subtree" -P sub1 ../shared_projects/subtree1 master && + check_equal ''"$(last_commit_message)"'' "Add sub1 subtree" +' + +# Store latest commit id for future use +expected_subtreeMergeCommit=$(last_commit_id) + +test_expect_success 'check if .gittrees file was created' ' + test -a '.gittrees' +' +# Now lets test if the .gittrees file has the correct information +# Hardcoded some expected results for checking data inside .gittrees file +expected_url='../shared_projects/subtree1' +expected_path='sub1' + +echo $expected_url>>expected_gittrees +echo $expected_path>>expected_gittrees +echo $expected_branch>>expected_gittrees +echo $expected_subtreeCommit>>expected_gittrees +echo $expected_subtreeMergeCommit>>expected_gittrees + +grep = .gittrees | cut -f2 -d"=" | cut -f2 -d" " > actual_gittrees + +test_expect_success 'check .gittrees file has the necessary changes' ' + test_cmp actual_gittrees expected_gittrees +' + +test_expect_success 'check subtree does not get created with incorrect remote url' ' + test_must_fail git subtree add -P s2 ../shared_projects/subbtree1 master +' + +test_expect_success 'check that subtree does not get created with incorrect branch' ' + test_must_fail git subtree add -P s2 ../shared_projects/subtree1 development +' + +test_expect_success 'add another subtree with master branch' ' + git subtree add -m "Add sub2 subtree" -P sub2 ../shared_projects/subtree2 master && + check_equal ''"$(last_commit_message)"'' "Add sub2 subtree" +' test_done -- 1.7.9 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html