commit 557db725c8ba1e1ed1efd51febd91476b965647b from: Stefan Sperling date: Thu Jun 13 21:33:23 2024 UTC show a more useful error when a reference name collides with another If a reference cannot be created because a file is present where a directory would need to be created to accomodate the new ref's name, report a name collision rather than an obscure mkstemps ENOTDIR error. issue found by Lucas commit - 9ae4c4eaf05d8dfead422805fa0f902e196b73d3 commit + 557db725c8ba1e1ed1efd51febd91476b965647b blob - c578dc9c58e835b547a901f7a3dbec472b4517fa blob + 070b80df0cce4e90b81489df1c9f71ce5c1c3cc7 --- lib/reference.c +++ lib/reference.c @@ -1206,6 +1206,12 @@ got_ref_write(struct got_reference *ref, struct got_re err = got_opentemp_named(&tmppath, &f, path, ""); if (err) { char *parent; + if (err->code == GOT_ERR_ERRNO && errno == ENOTDIR) { + err = got_error_fmt(GOT_ERR_BAD_REF_NAME, + "collision with an existing reference: %s", + got_ref_get_name(ref)); + goto done; + } if (!(err->code == GOT_ERR_ERRNO && errno == ENOENT)) goto done; err = got_path_dirname(&parent, path); blob - 12ee9f0325d237ae1d8a5a962b5aa23fb7261605 blob + 64e5549700453bd0afc70a70e8b3e31c3cde21db --- regress/cmdline/ref.sh +++ regress/cmdline/ref.sh @@ -170,12 +170,45 @@ test_ref_create() { test_done "$testroot" "$ret" return 1 fi + + # Create a ref with a / in its name + got ref -r $testroot/repo -c $commit_id refs/heads/commit/ref + ret=$? + if [ $ret -ne 0 ]; then + echo "got ref command failed unexpectedly" + test_done "$testroot" "$ret" + return 1 + fi + + # Create a ref with a name that collides with a file + got ref -r $testroot/repo -c $commit_id refs/heads/commitref/new \ + 2> $testroot/stderr + ret=$? + if [ $ret -eq 0 ]; then + echo "got ref command succeeded unexpectedly" + test_done "$testroot" "$ret" + return 1 + fi + + echo -n "got: collision with an existing reference: " \ + > $testroot/stderr.expected + echo "refs/heads/commitref/new: bad reference name" \ + >> $testroot/stderr.expected + cmp -s $testroot/stderr $testroot/stderr.expected + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stderr.expected $testroot/stderr + test_done "$testroot" "$ret" + return 1 + fi + got ref -r $testroot/repo -l > $testroot/stdout echo "HEAD: refs/heads/newref" > $testroot/stdout.expected echo -n "refs/got/worktree/base-" >> $testroot/stdout.expected cat $testroot/wt/.got/uuid | tr -d '\n' >> $testroot/stdout.expected echo ": $commit_id" >> $testroot/stdout.expected echo "refs/heads/anotherref: $commit_id" >> $testroot/stdout.expected + echo "refs/heads/commit/ref: $commit_id" >> $testroot/stdout.expected echo "refs/heads/commitref: $commit_id" >> $testroot/stdout.expected echo "refs/heads/master: $commit_id" >> $testroot/stdout.expected echo "refs/heads/newref: $commit_id" >> $testroot/stdout.expected