From: Omar Polo Subject: Re: checkout -E and existing files To: Stefan Sperling Cc: Christian Weisgerber , gameoftrees@openbsd.org Date: Sat, 16 Sep 2023 13:00:05 +0200 On 2023/09/16 11:44:56 +0200, Stefan Sperling wrote: > On Fri, Sep 15, 2023 at 11:42:22PM +0200, Omar Polo wrote: > > On 2023/09/15 22:14:19 +0200, Christian Weisgerber wrote: > > > Presumably got will eventually notice once the files that are > > > different are actually changed by some operation. > > > > `find . -type f -exec touch {} +' should be enough to make got aware. > > Not a great solution indeed. > > > > > I'm not sure what I was expecting, but the existing behavior seems ... > > > not useful? > > > > We could put a timestamp older than the one of the file upon the first > > checkout. Or just zero. That should trigger `got status' to actually > > look at the file contents. We should do this only for files that are > > already there however. > > Good idea. Set the file index timestamp to epoch if -E is used. > The next status crawl will be slow but should update timestamps for > all files, and should detect files that differ from their base blob. I was overly eager to optimize when I suggested to set {c,m}time to epoch in the fileindex when checking out over existing files because the usual (?) case would be to checkout over a previous checkout (or something that resembles it.) However, it seems easier to propagate the info upward from install_blob() rather than -E down from cmd_checkout(). diff just to illustrate, still lacking a regress. P.S. is the manpage wrong too by the way? It says that the statuses for checkout are A and E, no mention of ? is done. Should we return E for this case or add ? to the listing? diff /home/op/w/got commit - 01d78e9e349d8547e36bfe47e4c53acfcef2973d path + /home/op/w/got blob - a60bbbeee54da16d7504c7439574f7825bf1625a file + lib/worktree.c --- lib/worktree.c +++ lib/worktree.c @@ -1104,7 +1104,8 @@ 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, - int wt_fd, const char *path, struct got_object_id *blob_id) + int wt_fd, const char *path, struct got_object_id *blob_id, + int update_timestamps) { const struct got_error *err = NULL; struct got_fileindex_entry *new_ie; @@ -1116,7 +1117,7 @@ create_fileindex_entry(struct got_fileindex_entry **ne return err; err = got_fileindex_entry_update(new_ie, wt_fd, path, - blob_id->sha1, base_commit_id->sha1, 1); + blob_id->sha1, base_commit_id->sha1, update_timestamps); if (err) goto done; @@ -1152,7 +1153,8 @@ install_blob(struct got_worktree *worktree, const char const char *path, mode_t te_mode, mode_t st_mode, struct got_blob_object *blob, int restoring_missing_file, int reverting_versioned_file, int installing_bad_symlink, - int path_is_unversioned, struct got_repository *repo, + int path_is_unversioned, int *update_timestamps, + struct got_repository *repo, got_worktree_checkout_cb progress_cb, void *progress_arg); /* @@ -1298,7 +1300,7 @@ install_symlink(int *is_bad_symlink, struct got_worktr return install_blob(worktree, ondisk_path, path, GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob, restoring_missing_file, reverting_versioned_file, - 1, path_is_unversioned, repo, progress_cb, + 1, path_is_unversioned, NULL, repo, progress_cb, progress_arg); } if (len > 0) { @@ -1322,7 +1324,8 @@ install_symlink(int *is_bad_symlink, struct got_worktr err = install_blob(worktree, ondisk_path, path, GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob, restoring_missing_file, reverting_versioned_file, 1, - path_is_unversioned, repo, progress_cb, progress_arg); + path_is_unversioned, NULL, repo, + progress_cb, progress_arg); return err; } @@ -1385,7 +1388,7 @@ install_symlink(int *is_bad_symlink, struct got_worktr err = install_blob(worktree, ondisk_path, path, GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob, restoring_missing_file, reverting_versioned_file, 1, - path_is_unversioned, repo, + path_is_unversioned, NULL, repo, progress_cb, progress_arg); } else if (errno == ENOTDIR) { err = got_error_path(ondisk_path, @@ -1405,7 +1408,8 @@ install_blob(struct got_worktree *worktree, const char const char *path, mode_t te_mode, mode_t st_mode, struct got_blob_object *blob, int restoring_missing_file, int reverting_versioned_file, int installing_bad_symlink, - int path_is_unversioned, struct got_repository *repo, + int path_is_unversioned, int *update_timestamps, + struct got_repository *repo, got_worktree_checkout_cb progress_cb, void *progress_arg) { const struct got_error *err = NULL; @@ -1415,6 +1419,9 @@ install_blob(struct got_worktree *worktree, const char char *tmppath = NULL; mode_t mode; + if (update_timestamps) + *update_timestamps = 0; + mode = get_ondisk_perms(te_mode & S_IXUSR, GOT_DEFAULT_FILE_MODE); fd = open(ondisk_path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, mode); @@ -1438,6 +1445,8 @@ install_blob(struct got_worktree *worktree, const char ondisk_path); } else if (errno == EEXIST) { if (path_is_unversioned) { + if (update_timestamps) + *update_timestamps = 0; err = (*progress_cb)(progress_arg, GOT_STATUS_UNVERSIONED, path); goto done; @@ -1911,6 +1920,7 @@ update_blob(struct got_worktree *worktree, unsigned char status = GOT_STATUS_NO_CHANGE; struct stat sb; int fd1 = -1, fd2 = -1; + int update_timestamps; if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, path) == -1) return got_error_from_errno("asprintf"); @@ -2119,8 +2129,9 @@ update_blob(struct got_worktree *worktree, err = install_blob(worktree, ondisk_path, path, te->mode, sb.st_mode, blob, status == GOT_STATUS_MISSING, 0, 0, - status == GOT_STATUS_UNVERSIONED, repo, - progress_cb, progress_arg); + status == GOT_STATUS_UNVERSIONED, + &update_timestamps, + repo, progress_cb, progress_arg); } if (err) goto done; @@ -2132,7 +2143,7 @@ update_blob(struct got_worktree *worktree, } else { err = create_fileindex_entry(&ie, fileindex, worktree->base_commit_id, worktree->root_fd, path, - &blob->id); + &blob->id, update_timestamps); } if (err) goto done; @@ -2934,7 +2945,8 @@ add_file(struct got_worktree *worktree, struct got_fil err = install_blob(worktree, ondisk_path, path2, mode2, GOT_DEFAULT_FILE_MODE, blob2, restoring_missing_file, reverting_versioned_file, 0, - path_is_unversioned, repo, progress_cb, progress_arg); + path_is_unversioned, NULL, repo, + progress_cb, progress_arg); } if (err) return err; @@ -5289,7 +5301,7 @@ revert_file(void *arg, unsigned char status, unsigned ie->path, te ? te->mode : GOT_DEFAULT_FILE_MODE, got_fileindex_perms_to_st(ie), blob, - 0, 1, 0, 0, a->repo, + 0, 1, 0, 0, NULL, a->repo, a->progress_cb, a->progress_arg); } if (err)