commit - 8eecaf36f67e6c52dd667a6b96155045a7d6498d
commit + 44d03001f2c2417eb3821cdbd163e51b53c92461
blob - 9f943879d6192c047d028a05d65bd8a4480935bc
blob + 87be49d7f562408e06afc48fe61daabac15d8f3c
--- lib/worktree.c
+++ lib/worktree.c
struct commitable {
char *path;
+ char *in_repo_path;
char *ondisk_path;
unsigned char status;
struct got_object_id *id;
free_commitable(struct commitable *ct)
{
free(ct->path);
+ free(ct->in_repo_path);
free(ct->ondisk_path);
free(ct->id);
free(ct->base_id);
ct->mode = sb.st_mode;
}
+ if (asprintf(&ct->in_repo_path, "%s%s%s", a->worktree->path_prefix,
+ got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
+ relpath) == -1) {
+ err = got_error_from_errno();
+ goto done;
+ }
+
ct->status = status;
ct->id = NULL; /* will be filled in when blob gets created */
if (ct->status != GOT_STATUS_ADD) {
}
static const struct got_error *
+match_modified_subtree(int *modified, struct got_tree_entry *te,
+ const char *base_tree_path, struct got_pathlist_head *commitable_paths)
+{
+ const struct got_error *err = NULL;
+ struct got_pathlist_entry *pe;
+ char *te_path;
+
+ *modified = 0;
+
+ if (asprintf(&te_path, "%s%s%s", base_tree_path,
+ got_path_is_root_dir(base_tree_path) ? "" : "/",
+ te->name) == -1)
+ return got_error_from_errno();
+
+ TAILQ_FOREACH(pe, commitable_paths, entry) {
+ struct commitable *ct = pe->data;
+ char *ct_path;
+
+ if (asprintf(&ct_path, "%s%s%s", base_tree_path,
+ got_path_is_root_dir(base_tree_path) ? "" : "/",
+ te->name) == -1) {
+ err = got_error_from_errno();
+ break;
+ }
+
+ *modified = got_path_is_child(ct->in_repo_path, te_path,
+ strlen(te_path));
+ if (*modified)
+ break;
+ }
+
+ free(te_path);
+ return err;
+}
+
+static const struct got_error *
match_deleted_or_modified_ct(struct commitable **ctp,
struct got_tree_entry *te, const char *base_tree_path,
struct got_pathlist_head *commitable_paths)
struct commitable *ct = NULL;
if (S_ISDIR(te->mode)) {
+ int modified;
err = got_object_tree_entry_dup(&new_te, te);
if (err)
goto done;
- free(new_te->id);
- err = write_subtree(&new_te->id, te,
- path_base_tree, commitable_paths,
- status_cb, status_arg, repo);
+ err = match_modified_subtree(&modified, te,
+ path_base_tree, commitable_paths);
if (err)
goto done;
+ /* Avoid recursion into unmodified subtrees. */
+ if (modified) {
+ free(new_te->id);
+ err = write_subtree(&new_te->id, te,
+ path_base_tree, commitable_paths,
+ status_cb, status_arg, repo);
+ if (err)
+ goto done;
+ }
err = insert_tree_entry(new_te, &paths);
if (err)
goto done;