commit 6a390967d72bf5e54eb669a0cef5ea548662bbbf from: Stefan Sperling date: Fri Jul 14 15:14:00 2023 UTC prevent useless EEXIST errors filling up the global custom error array While checking out files, do not attempt to create every directory that exists in the repository tree without paying consideration to their existence on disk. Instead, let functions which add files worry about creating any missing parent directories. This shakes out two other bugs in broken symlink installation code which ended up passing an absolute path to add_dir_on_disk() and forgot to report progress in an unreachable code path that is now getting used. Problem reported by + ok naddy@ commit - 5fb50fce7978aa218c87ec7ac6c3f4e7bf20e5b3 commit + 6a390967d72bf5e54eb669a0cef5ea548662bbbf blob - 20e319355137e3ec594f1a28760412c19ab58905 blob + 0057e61e6db15e140ea00a36f04722389b25a0ba --- lib/worktree.c +++ lib/worktree.c @@ -396,6 +396,13 @@ add_dir_on_disk(struct got_worktree *worktree, const c { const struct got_error *err = NULL; char *abspath; + + /* We only accept worktree-relative paths here. */ + if (got_path_is_absolute(path)) { + return got_error_fmt(GOT_ERR_BAD_PATH, + "%s does not accept absolute paths: %s", + __func__, path); + } if (asprintf(&abspath, "%s/%s", worktree->root_path, path) == -1) return got_error_from_errno("asprintf"); @@ -1350,7 +1357,7 @@ install_symlink(int *is_bad_symlink, struct got_worktr err = got_path_dirname(&parent, ondisk_path); if (err) return err; - err = add_dir_on_disk(worktree, parent); + err = got_path_mkdir(parent); free(parent); if (err) return err; @@ -1360,6 +1367,12 @@ install_symlink(int *is_bad_symlink, struct got_worktr */ if (symlink(target_path, ondisk_path) != -1) { err = NULL; /* success */ + if (progress_cb) { + err = (*progress_cb)(progress_arg, + reverting_versioned_file ? + GOT_STATUS_REVERT : GOT_STATUS_ADD, + path); + } return err; } } @@ -2292,6 +2305,9 @@ diff_new(void *arg, struct got_tree_entry *te, const c return got_error(GOT_ERR_CANCELLED); if (got_object_tree_entry_is_submodule(te)) + return NULL; + + if (!S_ISREG(te->mode) && !S_ISLNK(te->mode)) return NULL; if (asprintf(&path, "%s%s%s", parent_path, @@ -2299,11 +2315,8 @@ diff_new(void *arg, struct got_tree_entry *te, const c == -1) return got_error_from_errno("asprintf"); - if (S_ISDIR(te->mode)) - err = add_dir_on_disk(a->worktree, path); - else - err = update_blob(a->worktree, a->fileindex, NULL, te, path, - a->repo, a->progress_cb, a->progress_arg); + err = update_blob(a->worktree, a->fileindex, NULL, te, path, + a->repo, a->progress_cb, a->progress_arg); free(path); return err;