Download raw body.
On Tue, Dec 08, 2020 at 10:31:25AM -0800, Yang Zhong wrote:
> Here's a small patch demonstrating the use of the new fd field in
> got_worktree. I modified got_fileindex_entry_update to take in an
> fd, which required all of its calls to be modified as well. As you
> said, fileindexes have their paths stored relative to the worktree's
> path already, so most of the time I can pass in a pre-existing
> relative path instead of the absolute one.
>
> This required me to add worktree fd fields to a few helpers as well
> as got_fileindex_entry_update itself. There is also one spot where
> I used got_path_skip_common_ancestor to create a relative path, in
> update_fileindex_after_commit. I thought that ct->path would work
> (replacing ct->ondisk_path), but it did not; I'm probably missing
> some of the nuances in this case.
The problem with ct->path might be that collect_commitables() prepends
a slash to the relative path that was fetched from the file index.
I don't remember why this was done. Perhaps this could be changed,
but we can deal with that later.
This patch looks very good to me. I only have some style nits.
The size of this patch is well chosen for code review. I suppose it is
not very easy to extract individual changes like this from everything
you've already done for the proof of concept patch. Well done!
I see several overlong lines in this patch.
Please wrap lines at 80 columns, ideally a bit less than 80.
Indentation uses tabs for regular lines and 4 spaces for lines
that continue a statement.
Example from the OpenBSD style(9) man page:
z = a + really + long + statement + that + needs +
two + lines + gets + indented + four + spaces +
on + the + second + and + subsequent + lines;
More below:
> diff --git a/lib/fileindex.c b/lib/fileindex.c
> index b46dbb29..ce162817 100644
> --- a/lib/fileindex.c
> +++ b/lib/fileindex.c
> @@ -88,15 +88,15 @@ got_fileindex_perms_to_st(struct got_fileindex_entry *ie)
>
> const struct got_error *
> got_fileindex_entry_update(struct got_fileindex_entry *ie,
> - const char *ondisk_path, uint8_t *blob_sha1, uint8_t *commit_sha1,
> + int wt_fd, const char *ondisk_path, uint8_t *blob_sha1, uint8_t *commit_sha1,
> int update_timestamps)
> {
> struct stat sb;
>
> - if (lstat(ondisk_path, &sb) != 0) {
> + if (fstatat(wt_fd, ondisk_path, &sb, AT_SYMLINK_NOFOLLOW) != 0) {
> if (!((ie->flags & GOT_FILEIDX_F_NO_FILE_ON_DISK) &&
> errno == ENOENT))
> - return got_error_from_errno2("lstat", ondisk_path);
> + return got_error_from_errno2("fstatat", ondisk_path);
> sb.st_mode = GOT_DEFAULT_FILE_MODE;
> } else {
> if (sb.st_mode & S_IFDIR)
> diff --git a/lib/got_lib_fileindex.h b/lib/got_lib_fileindex.h
> index f1005832..537374d7 100644
> --- a/lib/got_lib_fileindex.h
> +++ b/lib/got_lib_fileindex.h
> @@ -108,7 +108,7 @@ uint16_t got_fileindex_perms_from_st(struct stat *);
> mode_t got_fileindex_perms_to_st(struct got_fileindex_entry *);
>
> const struct got_error *got_fileindex_entry_update(struct got_fileindex_entry *,
> - const char *, uint8_t *, uint8_t *, int);
> + int, const char *, uint8_t *, uint8_t *, int);
> const struct got_error *got_fileindex_entry_alloc(struct got_fileindex_entry **,
> const char *);
> void got_fileindex_entry_free(struct got_fileindex_entry *);
> diff --git a/lib/worktree.c b/lib/worktree.c
> index 8bf4b7ff..8994bf43 100644
> --- a/lib/worktree.c
> +++ b/lib/worktree.c
> @@ -1175,7 +1175,7 @@ done:
> static const struct got_error *
> create_fileindex_entry(struct got_fileindex_entry **new_iep,
> struct got_fileindex *fileindex, struct got_object_id *base_commit_id,
> - const char *ondisk_path, const char *path, struct got_object_id *blob_id)
> + int wt_fd, const char *path, struct got_object_id *blob_id)
The base_commit_id and wt_fd arguments fall out of struct worktree.
I can imagine naddy grinding his teeth at the sight of this and plotting
a plan to reduce the number of parameters by passing a 'struct worktree *'
instead as soon as you commit this change :)
> {
> const struct got_error *err = NULL;
> struct got_fileindex_entry *new_ie;
> @@ -1186,7 +1186,7 @@ create_fileindex_entry(struct got_fileindex_entry **new_iep,
> if (err)
> return err;
>
> - err = got_fileindex_entry_update(new_ie, ondisk_path,
> + err = got_fileindex_entry_update(new_ie, wt_fd, path,
> blob_id->sha1, base_commit_id->sha1, 1);
> if (err)
> goto done;
> @@ -1861,11 +1861,11 @@ done:
> * we had to run a full content comparison to find out.
> */
> static const struct got_error *
> -sync_timestamps(char *ondisk_path, unsigned char status,
> +sync_timestamps(int wt_fd, const char *path, unsigned char status,
> struct got_fileindex_entry *ie, struct stat *sb)
> {
> if (status == GOT_STATUS_NO_CHANGE && stat_info_differs(ie, sb))
> - return got_fileindex_entry_update(ie, ondisk_path,
> + return got_fileindex_entry_update(ie, wt_fd, path,
> ie->blob_sha1, ie->commit_sha1, 1);
>
> return NULL;
> @@ -1918,7 +1918,7 @@ update_blob(struct got_worktree *worktree,
> if (got_fileindex_entry_has_commit(ie) &&
> memcmp(ie->commit_sha1, worktree->base_commit_id->sha1,
> SHA1_DIGEST_LENGTH) == 0) {
> - err = sync_timestamps(ondisk_path, status, ie, &sb);
> + err = sync_timestamps(worktree->root_fd, path, status, ie, &sb);
> if (err)
> goto done;
> err = (*progress_cb)(progress_arg, GOT_STATUS_EXISTS,
> @@ -1928,7 +1928,7 @@ update_blob(struct got_worktree *worktree,
> if (got_fileindex_entry_has_blob(ie) &&
> memcmp(ie->blob_sha1, te->id.sha1,
> SHA1_DIGEST_LENGTH) == 0) {
> - err = sync_timestamps(ondisk_path, status, ie, &sb);
> + err = sync_timestamps(worktree->root_fd, path, status, ie, &sb);
> goto done;
> }
> }
> @@ -1987,17 +1987,17 @@ update_blob(struct got_worktree *worktree,
> * Otherwise, a future status walk would treat them as
> * unmodified files again.
> */
> - err = got_fileindex_entry_update(ie, ondisk_path,
> + err = got_fileindex_entry_update(ie, worktree->root_fd, path,
> blob->id.sha1, worktree->base_commit_id->sha1,
> update_timestamps);
> } else if (status == GOT_STATUS_MODE_CHANGE) {
> - err = got_fileindex_entry_update(ie, ondisk_path,
> + err = got_fileindex_entry_update(ie, worktree->root_fd, path,
> blob->id.sha1, worktree->base_commit_id->sha1, 0);
> } else if (status == GOT_STATUS_DELETE) {
> err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
> if (err)
> goto done;
> - err = got_fileindex_entry_update(ie, ondisk_path,
> + err = got_fileindex_entry_update(ie, worktree->root_fd, path,
> blob->id.sha1, worktree->base_commit_id->sha1, 0);
> if (err)
> goto done;
> @@ -2020,11 +2020,11 @@ update_blob(struct got_worktree *worktree,
> goto done;
>
> if (ie) {
> - err = got_fileindex_entry_update(ie, ondisk_path,
> + err = got_fileindex_entry_update(ie, worktree->root_fd, path,
> blob->id.sha1, worktree->base_commit_id->sha1, 1);
> } else {
> err = create_fileindex_entry(&ie, fileindex,
> - worktree->base_commit_id, ondisk_path, path,
> + worktree->base_commit_id, worktree->root_fd, path,
> &blob->id);
> }
> if (err)
> @@ -2124,7 +2124,7 @@ delete_blob(struct got_worktree *worktree, struct got_fileindex *fileindex,
> * Preserve the working file and change the deleted blob's
> * entry into a schedule-add entry.
> */
> - err = got_fileindex_entry_update(ie, ondisk_path, NULL, NULL,
> + err = got_fileindex_entry_update(ie, worktree->root_fd, ie->path, NULL, NULL,
> 0);
> } else {
> err = (*progress_cb)(progress_arg, GOT_STATUS_DELETE, ie->path);
> @@ -2933,7 +2933,7 @@ merge_file_cb(void *arg, struct got_blob_object *blob1,
> goto done;
> if (status == GOT_STATUS_DELETE) {
> err = got_fileindex_entry_update(ie,
> - ondisk_path, blob2->id.sha1,
> + a->worktree->root_fd, path2, blob2->id.sha1,
> a->worktree->base_commit_id->sha1, 0);
> if (err)
> goto done;
> @@ -2955,7 +2955,7 @@ merge_file_cb(void *arg, struct got_blob_object *blob1,
> err = got_fileindex_entry_alloc(&ie, path2);
> if (err)
> goto done;
> - err = got_fileindex_entry_update(ie, ondisk_path,
> + err = got_fileindex_entry_update(ie, a->worktree->root_fd, path2,
> NULL, NULL, 1);
> if (err) {
> got_fileindex_entry_free(ie);
> @@ -3775,7 +3775,7 @@ schedule_addition(void *arg, unsigned char status, unsigned char staged_status,
> err = got_fileindex_entry_alloc(&ie, relpath);
> if (err)
> goto done;
> - err = got_fileindex_entry_update(ie, ondisk_path, NULL, NULL, 1);
> + err = got_fileindex_entry_update(ie, a->worktree->root_fd, relpath, NULL, NULL, 1);
> if (err) {
> got_fileindex_entry_free(ie);
> goto done;
> @@ -4581,8 +4581,8 @@ revert_file(void *arg, unsigned char status, unsigned char staged_status,
> goto done;
> if (status == GOT_STATUS_DELETE ||
> status == GOT_STATUS_MODE_CHANGE) {
> - err = got_fileindex_entry_update(ie,
> - ondisk_path, blob->id.sha1,
> + err = got_fileindex_entry_update(ie, a->worktree->root_fd,
> + relpath, blob->id.sha1,
> a->worktree->base_commit_id->sha1, 1);
> if (err)
> goto done;
> @@ -5285,18 +5285,25 @@ done:
> }
>
> static const struct got_error *
> -update_fileindex_after_commit(struct got_pathlist_head *commitable_paths,
> +update_fileindex_after_commit(struct got_worktree *worktree, struct got_pathlist_head *commitable_paths,
> struct got_object_id *new_base_commit_id, struct got_fileindex *fileindex,
> int have_staged_files)
> {
> const struct got_error *err = NULL;
> struct got_pathlist_entry *pe;
> + char *relpath = NULL;
>
> TAILQ_FOREACH(pe, commitable_paths, entry) {
> struct got_fileindex_entry *ie;
> struct got_commitable *ct = pe->data;
>
> ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
> +
> + err = got_path_skip_common_ancestor(&relpath,
> + worktree->root_path, ct->ondisk_path);
> + if (err)
> + goto done;
> +
> if (ie) {
> if (ct->status == GOT_STATUS_DELETE ||
> ct->staged_status == GOT_STATUS_DELETE) {
> @@ -5306,32 +5313,38 @@ update_fileindex_after_commit(struct got_pathlist_head *commitable_paths,
> got_fileindex_entry_stage_set(ie,
> GOT_FILEIDX_STAGE_NONE);
> got_fileindex_entry_staged_filetype_set(ie, 0);
> - err = got_fileindex_entry_update(ie,
> - ct->ondisk_path, ct->staged_blob_id->sha1,
> +
> + err = got_fileindex_entry_update(ie, worktree->root_fd,
> + relpath, ct->staged_blob_id->sha1,
> new_base_commit_id->sha1,
> !have_staged_files);
> } else
> - err = got_fileindex_entry_update(ie,
> - ct->ondisk_path, ct->blob_id->sha1,
> + err = got_fileindex_entry_update(ie, worktree->root_fd,
> + relpath, ct->blob_id->sha1,
> new_base_commit_id->sha1,
> !have_staged_files);
> } else {
> err = got_fileindex_entry_alloc(&ie, pe->path);
> if (err)
> - break;
> - err = got_fileindex_entry_update(ie, ct->ondisk_path,
> + goto done;
> + err = got_fileindex_entry_update(ie, worktree->root_fd, relpath,
> ct->blob_id->sha1, new_base_commit_id->sha1, 1);
> if (err) {
> got_fileindex_entry_free(ie);
> - break;
> + goto done;
> }
> err = got_fileindex_entry_add(fileindex, ie);
> if (err) {
> got_fileindex_entry_free(ie);
> - break;
> + goto done;
> }
> }
> + free(relpath); //NOTE add done
Hmm. I don't understand what this comment is trying to tell me.
Style nit: no C++-style comments please, simply because it goes
against the OpenBSD style(9) rules. (I don't really care about comment
style myself; I just want to avoid having to sweep the code base for
stuff like this in the event that Got gets imported into the OpenBSD
base system some day...)
> + relpath = NULL;
> }
> +done:
> + if (relpath)
> + free(relpath);
> return err;
> }
>
> @@ -5662,7 +5675,7 @@ got_worktree_commit(struct got_object_id **new_commit_id,
> if (err)
> goto done;
>
> - err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
> + err = update_fileindex_after_commit(worktree, &commitable_paths, *new_commit_id,
> fileindex, have_staged_files);
> sync_err = sync_fileindex(fileindex, fileindex_path);
> if (sync_err && err == NULL)
> @@ -6248,7 +6261,7 @@ rebase_commit(struct got_object_id **new_commit_id,
> if (err)
> goto done;
>
> - err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
> + err = update_fileindex_after_commit(worktree, &commitable_paths, *new_commit_id,
> fileindex, 0);
> sync_err = sync_fileindex(fileindex, fileindex_path);
> if (sync_err && err == NULL)