don't visit added subtrees reundantly
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
diff --git a/lib/worktree.c b/lib/worktree.c
index bcc5c7a..3672855 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -2205,7 +2205,6 @@ struct commitable {
unsigned char status;
struct got_object_id *id;
struct got_object_id *base_id;
- struct got_object_id *tree_id;
};
static void
@@ -2214,7 +2213,6 @@ free_commitable(struct commitable *ct)
free(ct->path);
free(ct->id);
free(ct->base_id);
- free(ct->tree_id);
free(ct);
}
@@ -2270,10 +2268,6 @@ collect_commitables(void *arg, unsigned char status, const char *relpath,
goto done;
}
}
- err = got_object_id_by_path(&ct->tree_id, a->repo,
- a->worktree->base_commit_id, parent_path);
- if (err)
- goto done;
ct->path = strdup(path);
if (ct->path == NULL) {
err = got_error_from_errno();
@@ -2305,7 +2299,7 @@ write_subtree(struct got_object_id **new_subtree_id,
char *subpath;
if (asprintf(&subpath, "%s%s%s", parent_path,
- parent_path[0] == '\0' ? "" : "/", te->name) == -1)
+ got_path_is_root_dir(parent_path) ? "" : "/", te->name) == -1)
return got_error_from_errno();
err = got_object_open_as_tree(&subtree, repo, te->id);
@@ -2523,6 +2517,8 @@ write_tree(struct got_object_id **new_tree_id,
goto done;
} else {
char *subtree_path;
+ struct got_pathlist_entry *pe2;
+ int visited = 0;
*slash = '\0'; /* trim trailing path components */
@@ -2534,18 +2530,27 @@ write_tree(struct got_object_id **new_tree_id,
err = got_error_from_errno();
goto done;
}
- if (asprintf(&subtree_path, "%s/%s", path_base_tree,
+ if (asprintf(&subtree_path, "%s%s%s", path_base_tree,
+ got_path_is_root_dir(path_base_tree) ? "" : "/",
child_path) == -1) {
err = got_error_from_errno();
goto done;
}
- err = write_subtree(&new_te->id, NULL, subtree_path,
+ TAILQ_FOREACH(pe2, &paths, entry) {
+ if (got_path_cmp(subtree_path, pe2->path) != 0)
+ continue;
+ visited = 1;
+ break;
+ }
+ if (visited)
+ continue;
+
+ err = write_tree(&new_te->id, NULL, subtree_path,
commitable_paths, status_cb, status_arg, repo);
free(subtree_path);
if (err)
goto done;
}
-
err = insert_tree_entry(new_te, &paths);
if (err)
goto done;
diff --git a/regress/cmdline/commit.sh b/regress/cmdline/commit.sh
index 54f8171..3d14f78 100755
--- a/regress/cmdline/commit.sh
+++ b/regress/cmdline/commit.sh
@@ -50,4 +50,37 @@ function test_commit_basic {
test_done "$testroot" "$ret"
}
+function test_commit_new_subdir {
+ local testroot=`test_init commit_new_subdir`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ mkdir -p $testroot/wt/d
+ echo "new file" > $testroot/wt/d/new
+ echo "another new file" > $testroot/wt/d/new2
+ (cd $testroot/wt && got add d/new >/dev/null)
+ (cd $testroot/wt && got add d/new2 >/dev/null)
+
+ (cd $testroot/wt && \
+ got commit -m 'test commit_new_subdir' > $testroot/stdout)
+
+ local head_rev=`git_show_head $testroot/repo`
+ echo "A d/new" > $testroot/stdout.expected
+ echo "A d/new2" >> $testroot/stdout.expected
+ echo "created commit $head_rev" >> $testroot/stdout.expected
+
+ cmp $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
+ test_done "$testroot" "$ret"
+}
+
run_test test_commit_basic
+run_test test_commit_new_subdir