commit - c29c428a5f2db009ac7f83085fe96c62bf48ee79
commit + 7f47418fd49bc98fe4570c139767c057cd066409
blob - 98571cf64193a2e536f09fedf3b82a1f61dfdb9a
blob + e658e622b058b0f31f698572b39ed94a026bc154
--- got/got.c
+++ got/got.c
exit(1);
}
+static void
+show_worktree_base_ref_warning(void)
+{
+ fprintf(stderr, "%s: warning: could not create a reference "
+ "to the work tree's base commit; the commit could be "
+ "garbage-collected by Git; making the repository "
+ "writable and running 'got update' will prevent this\n",
+ getprogname());
+}
+
+struct got_checkout_progress_arg {
+ const char *worktree_path;
+ int had_base_commit_ref_error;
+};
+
static const struct got_error *
checkout_progress(void *arg, unsigned char status, const char *path)
{
- char *worktree_path = arg;
+ struct got_checkout_progress_arg *a = arg;
/* Base commit bump happens silently. */
if (status == GOT_STATUS_BUMP_BASE)
+ return NULL;
+
+ if (status == GOT_STATUS_BASE_REF_ERR) {
+ a->had_base_commit_ref_error = 1;
return NULL;
+ }
while (path[0] == '/')
path++;
- printf("%c %s/%s\n", status, worktree_path, path);
+ printf("%c %s/%s\n", status, a->worktree_path, path);
return NULL;
}
char *commit_id_str = NULL;
int ch, same_path_prefix;
struct got_pathlist_head paths;
+ struct got_checkout_progress_arg cpa;
TAILQ_INIT(&paths);
error = got_pathlist_append(&paths, "", NULL);
if (error)
goto done;
+ cpa.worktree_path = worktree_path;
+ cpa.had_base_commit_ref_error = 0;
error = got_worktree_checkout_files(worktree, &paths, repo,
- checkout_progress, worktree_path, check_cancelled, NULL);
+ checkout_progress, &cpa, check_cancelled, NULL);
if (error != NULL)
goto done;
printf("Now shut up and hack\n");
+ if (cpa.had_base_commit_ref_error)
+ show_worktree_base_ref_warning();
done:
got_pathlist_free(&paths);
{
int *did_something = arg;
- if (status == GOT_STATUS_EXISTS)
+ if (status == GOT_STATUS_EXISTS ||
+ status == GOT_STATUS_BASE_REF_ERR)
return NULL;
*did_something = 1;
blob - 09b7625b9d125ef255c71f181a0dad5efddd31d0
blob + 7ee3eaeaa50ee972174740c861e33c472d33aa9a
--- include/got_worktree.h
+++ include/got_worktree.h
#define GOT_STATUS_REVERT 'R'
#define GOT_STATUS_CANNOT_DELETE 'd'
#define GOT_STATUS_BUMP_BASE 'b'
+#define GOT_STATUS_BASE_REF_ERR 'B'
/*
* Attempt to initialize a new work tree on disk.
blob - a8f682710c80855da6d8bcaa9a34b34ede492b9f
blob + ba58428f5804dfcea39d26b7c33082de42e28ab5
--- lib/worktree.c
+++ lib/worktree.c
struct diff_cb_arg arg;
err = ref_base_commit(worktree, repo);
- if (err)
- goto done;
+ if (err) {
+ if (!(err->code == GOT_ERR_ERRNO && errno == EACCES))
+ goto done;
+ err = (*progress_cb)(progress_arg,
+ GOT_STATUS_BASE_REF_ERR, worktree->root_path);
+ if (err)
+ return err;
+ }
err = got_object_open_as_commit(&commit, repo,
worktree->base_commit_id);
blob - 76ad000185ee0b02fa1a80d4ee24110a2fab7191
blob + 34747be3c1c93a3c475b7e42583dca7f4ae844a4
--- regress/cmdline/checkout.sh
+++ regress/cmdline/checkout.sh
fi
test_done "$testroot" "$ret"
}
+
+function test_checkout_read_only {
+ local testroot=`test_init checkout_read_only`
+
+ # Make the repostiory read-only
+ chmod -R a-w $testroot/repo
+
+ echo "A $testroot/wt/alpha" > $testroot/stdout.expected
+ echo "A $testroot/wt/beta" >> $testroot/stdout.expected
+ echo "A $testroot/wt/epsilon/zeta" >> $testroot/stdout.expected
+ echo "A $testroot/wt/gamma/delta" >> $testroot/stdout.expected
+ echo "Now shut up and hack" >> $testroot/stdout.expected
+
+ got checkout $testroot/repo $testroot/wt \
+ > $testroot/stdout 2> $testroot/stderr
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ echo -n "got: warning: could not create a reference " \
+ > $testroot/stderr.expected
+ echo -n "to the work tree's base commit; the commit could " \
+ >> $testroot/stderr.expected
+ echo -n "be garbage-collected by Git; making the repository " \
+ >> $testroot/stderr.expected
+ echo "writable and running 'got update' will prevent this" \
+ >> $testroot/stderr.expected
+ cmp -s $testroot/stderr.expected $testroot/stderr
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stderr.expected $testroot/stderr
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ echo "alpha" > $testroot/content.expected
+ echo "beta" >> $testroot/content.expected
+ echo "zeta" >> $testroot/content.expected
+ echo "delta" >> $testroot/content.expected
+ cat $testroot/wt/alpha $testroot/wt/beta $testroot/wt/epsilon/zeta \
+ $testroot/wt/gamma/delta > $testroot/content
+
+ cmp -s $testroot/content.expected $testroot/content
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/content.expected $testroot/content
+ fi
+ chmod -R u+w $testroot/repo # make repo cleanup work
+ test_done "$testroot" "$ret"
+}
+
run_test test_checkout_basic
run_test test_checkout_dir_exists
run_test test_checkout_dir_not_empty
run_test test_checkout_commit_from_wrong_branch
run_test test_checkout_tag
run_test test_checkout_ignores_submodules
+run_test test_checkout_read_only