commit - 971d0123bfde09ec62689dbf7e2d9a68e143f4b6
commit + 3d800fb8c5236335129e5a017113967bda6cd62c
blob - 0f43972acc8ee969e3863b582c941b718f58b067
blob + bd0801b81a4b51afcaa87fe0f3a6ae5a5692f8f0
--- got/got.c
+++ got/got.c
return NULL;
}
+
+struct wt_commitable_path_arg {
+ struct got_pathlist_head *commit_paths;
+ int *has_changes;
+};
/*
- * Shortcut work tree status callback to determine if the set of
- * paths scanned has at least one versioned path that is modified.
- * Set arg and return GOT_ERR_FILE_MODIFIED as soon as a path is
- * passed with a status that is neither unchanged nor unversioned.
+ * Shortcut work tree status callback to determine if the set of paths scanned
+ * has at least one versioned path that is being modified and, if not NULL, is
+ * in the arg->commit_paths list. Set arg and return GOT_ERR_FILE_MODIFIED as
+ * soon as a path is passed with a status that satisfies this criteria.
*/
static const struct got_error *
-worktree_has_changed_path(void *arg, unsigned char status,
+worktree_has_commitable_path(void *arg, unsigned char status,
unsigned char staged_status, const char *path,
struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
struct got_object_id *commit_id, int dirfd, const char *de_name)
{
- int *has_changes = arg;
+ struct wt_commitable_path_arg *a = arg;
if (status == staged_status && (status == GOT_STATUS_DELETE))
status = GOT_STATUS_NO_CHANGE;
if (!(status == GOT_STATUS_NO_CHANGE ||
status == GOT_STATUS_UNVERSIONED) ||
staged_status != GOT_STATUS_NO_CHANGE) {
- *has_changes = 1;
- return got_error(GOT_ERR_FILE_MODIFIED);
+ if (a->commit_paths != NULL) {
+ struct got_pathlist_entry *pe;
+
+ TAILQ_FOREACH(pe, a->commit_paths, entry) {
+ if (strncmp(path, pe->path,
+ pe->path_len) == 0) {
+ *a->has_changes = 1;
+ break;
+ }
+ }
+ } else
+ *a->has_changes = 1;
+
+ if (*a->has_changes)
+ return got_error(GOT_ERR_FILE_MODIFIED);
}
return NULL;
/*
* Check that the changeset of the commit identified by id is
- * comprised of at least one path that is modified in the work tree.
+ * comprised of at least one modified path that is being committed.
*/
static const struct got_error *
-commit_path_changed_in_worktree(int *add_logmsg, struct got_object_id *id,
- struct got_worktree *worktree, struct got_repository *repo)
+commit_path_changed_in_worktree(struct wt_commitable_path_arg *wcpa,
+ struct got_object_id *id, struct got_worktree *worktree,
+ struct got_repository *repo)
{
const struct got_error *err;
struct got_pathlist_head paths;
goto done;
err = got_worktree_status(worktree, &paths, repo, 0,
- worktree_has_changed_path, add_logmsg, check_cancelled, NULL);
+ worktree_has_commitable_path, wcpa, check_cancelled, NULL);
if (err && err->code == GOT_ERR_FILE_MODIFIED) {
/*
* At least one changed path in the referenced commit is
struct got_reflist_entry *re;
struct got_commit_object *commit = NULL;
struct got_object_id *commit_id = NULL;
+ struct wt_commitable_path_arg wcpa;
char *uuidstr = NULL;
TAILQ_INIT(&refs);
if (err)
goto done;
- err = commit_path_changed_in_worktree(&has_changes, commit_id,
+ wcpa.commit_paths = NULL;
+ wcpa.has_changes = &has_changes;
+
+ err = commit_path_changed_in_worktree(&wcpa, commit_id,
worktree, repo);
if (err)
goto done;
* to be scheduled for removal on successful commit.
*/
static const struct got_error *
-lookup_logmsg_ref(char **logmsg, struct got_reflist_head *matched_refs,
- struct got_worktree *worktree, struct got_repository *repo)
+lookup_logmsg_ref(char **logmsg, struct got_pathlist_head *paths,
+ struct got_reflist_head *matched_refs, struct got_worktree *worktree,
+ struct got_repository *repo)
{
const struct got_error *err;
struct got_commit_object *commit = NULL;
goto done;
TAILQ_FOREACH(re, &refs, entry) {
- const char *refname, *type;
- int add_logmsg = 0;
+ const char *refname, *type;
+ struct wt_commitable_path_arg wcpa;
+ int add_logmsg = 0;
refname = got_ref_get_name(re->ref);
if (err)
goto done;
- err = commit_path_changed_in_worktree(&add_logmsg, id,
+ wcpa.commit_paths = paths;
+ wcpa.has_changes = &add_logmsg;
+
+ err = commit_path_changed_in_worktree(&wcpa, id,
worktree, repo);
if (err)
goto done;
goto done;
if (prepared_logmsg == NULL) {
- error = lookup_logmsg_ref(&prepared_logmsg, &refs,
+ error = lookup_logmsg_ref(&prepared_logmsg,
+ argc > 0 ? &paths : NULL, &refs,
worktree, repo);
if (error)
goto done;