Page MenuHomePhabricator

Arcanist unable to patch with initial commit
Closed, DuplicatePublic

Description

Phabricator installation versions

phabricator 53bc57ecef8739c29105eb52b1f118c0402e2c6c (Sat, Apr 29) (branched from 103b4507132d535fea111f3ff7bfc9904d02aa9f on origin)
arcanist ada63de9722e4b60ec9f0900a757b5b3873fc2f7 (Sat, Apr 29) (branched from c243cbbd9fc701ca9555672ea5c1666ea154898f on origin)
phutil d02cc05931b02c684d4c729510090591ca45f951 (Sat, Apr 29) (branched from 5ac2ca1214890d865bc57fab2715a322fdf02ab6 on origin)

Packaged arcanist matches the same versions for libphutil and arcanist, tracking stable

The Solus Phabricator instance is using Diffusion to host, at present, over 3k repositories. The workflow effectively stems from creating a package request via
Maniphest, then a Core Team member will construct a new repository in Diffusion. The user then provides an arc diff against this repository, which the reviewers
will then arc patch && arc land to merge into the initial history. All subsequent updates are handled via arc diff, unless via an explicit maintainer.

When the repository is newly created and contains no history, arc patch is unable to apply to an empty git:

 ✓  ikey@solus-bdw  ~/Solus  git clone ssh://vcs@dev.solus-project.com/source/luminance-hdr.git
Cloning into 'luminance-hdr'...
remote: Counting objects: 2, done.
remote: Total 2 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (2/2), done.
 ✓  ikey@solus-bdw  ~/Solus  cd luminance-hdr 
 ✓  ikey@solus-bdw  …/Solus/luminance-hdr   master  arc patch D38 --trace
 ARGV  '/usr/share/php/arcanist/bin/../scripts/arcanist.php' 'patch' 'D38' '--trace'
 LOAD  Loaded "phutil" from "/usr/share/php/libphutil/src".
 LOAD  Loaded "arcanist" from "/usr/share/php/arcanist/src".
Config: Reading user configuration file "/home/ikey/.arcrc"...
Config: Did not find system configuration at "/etc/arcconfig".
Working Copy: Unable to find .arcconfig in any of these locations: /home/ikey/Solus/luminance-hdr/.arcconfig.
Working Copy: Path "/home/ikey/Solus/luminance-hdr" is part of `git` working copy "/home/ikey/Solus/luminance-hdr".
Working Copy: Project root is at "/home/ikey/Solus/luminance-hdr".
Config: Did not find local configuration at "/home/ikey/Solus/luminance-hdr/.git/arc/config".
>>> [0] <conduit> differential.querydiffs() <bytes = 73>
>>> [1] <http> https://dev.solus-project.com/api/differential.querydiffs
<<< [1] <http> 262,403 us
<<< [0] <conduit> 262,708 us
>>> [2] <conduit> user.whoami() <bytes = 117>
>>> [3] <http> https://dev.solus-project.com/api/user.whoami
<<< [3] <http> 121,704 us
<<< [2] <conduit> 121,870 us
>>> [4] <conduit> differential.querydiffs() <bytes = 154>
>>> [5] <http> https://dev.solus-project.com/api/differential.querydiffs
<<< [5] <http> 142,534 us
<<< [4] <conduit> 142,709 us
>>> [6] <exec> $ git symbolic-ref --quiet HEAD
<<< [6] <exec> 7,277 us
>>> [7] <exec> $ git rev-parse --symbolic-full-name 'master'@{upstream}
<<< [7] <exec> 3,715 us
>>> [8] <exec> $ git --version
<<< [8] <exec> 3,501 us
>>> [9] <exec> $ git ls-remote --get-url 'origin'
<<< [9] <exec> 3,510 us
>>> [10] <conduit> repository.query() <bytes = 231>
>>> [11] <http> https://dev.solus-project.com/api/repository.query
<<< [11] <http> 143,543 us
<<< [10] <conduit> 143,697 us
>>> [12] <exec> $ git diff --no-ext-diff --no-textconv --submodule=short --raw 'HEAD' --
>>> [13] <exec> $ git ls-files --others --exclude-standard
<<< [12] <exec> 5,649 us
<<< [13] <exec> 4,658 us
>>> [14] <exec> $ git diff-files --name-only
<<< [14] <exec> 3,626 us
>>> [15] <exec> $ git show -s --format='%H' '4b825dc642cb6eb9a060e54bf8d69288fbee4904' --
<<< [15] <exec> 3,747 us
>>> [16] <exec> $ git symbolic-ref --quiet HEAD
<<< [16] <exec> 3,659 us
>>> [17] <exec> $ git rev-parse --verify 'arcpatch-D38'
<<< [17] <exec> 3,624 us
>>> [18] <exec> $ git show -s --format='%H' '4b825dc642cb6eb9a060e54bf8d69288fbee4904' --
<<< [18] <exec> 3,593 us
>>> [19] <exec> $ git checkout -b 'arcpatch-D38' 'tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904'
<<< [19] <exec> 4,348 us

[2017-05-07 16:37:19] EXCEPTION: (CommandException) Command failed with error #128!
COMMAND
git checkout -b 'arcpatch-D38' 'tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904'

STDOUT
(empty)

STDERR
fatal: Cannot update paths and switch to branch 'arcpatch-D38' at the same time.
Did you intend to checkout 'tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904' which can not be resolved as commit?
 at [<phutil>/src/future/exec/ExecFuture.php:369]
arcanist(), phutil()
  #0 ExecFuture::resolvex() called at [<arcanist>/src/repository/api/ArcanistRepositoryAPI.php:406]
  #1 ArcanistRepositoryAPI::execxLocal(string, string, string) called at [<arcanist>/src/workflow/ArcanistPatchWorkflow.php:310]
  #2 ArcanistPatchWorkflow::createBranch(ArcanistBundle, boolean) called at [<arcanist>/src/workflow/ArcanistPatchWorkflow.php:453]
  #3 ArcanistPatchWorkflow::run() called at [<arcanist>/src/workflow/ArcanistPatchWorkflow.php:397]
  #4 ArcanistPatchWorkflow::run() called at [<arcanist>/scripts/arcanist.php:394]

The error here is two fold, in that with empty commits (thus no proper tree), it cannot checkout and branch at the same time.
Additionally, when there is no history at all, we're trying to check out the so-called "magic root commit" tree.

At this time I'm presently unable to sign a CLA (apologies) due to employment situation, however what I can do is make the following
diff Public Domain and relinquish any claims to it, should Phacility wish to correct this behaviour in upstream Phabricator.

diff --git a/src/workflow/ArcanistPatchWorkflow.php b/src/workflow/ArcanistPatchWorkflow.php
index c1a8f878..da2d787e 100644
--- a/src/workflow/ArcanistPatchWorkflow.php
+++ b/src/workflow/ArcanistPatchWorkflow.php
@@ -303,15 +303,21 @@ EOTEXT
       $branch_name = $this->getBranchName($bundle);
       $base_revision = $bundle->getBaseRevision();
 
-      if ($base_revision && $has_base_revision) {
+      // We may be applying the initial commit to this repository, so skip
+      // the base revision in this instance.
+      if ($base_revision && $has_base_revision && $base_revision != ArcanistGitAPI::GIT_MAGIC_ROOT_COMMIT) {
         $base_revision = $repository_api->getCanonicalRevisionName(
           $base_revision);
         $repository_api->execxLocal(
-          'checkout -b %s %s',
+          'branch %s %s',
           $branch_name,
           $base_revision);
+        $repository_api->execxLocal(
+          'checkout %s',
+          $branch_name);
       } else {
-        $repository_api->execxLocal('checkout -b %s', $branch_name);
+        $repository_api->execxLocal('branch %s', $branch_name);
+        $repository_api->execxLocal('checkout %s', $branch_name);
       }
 
       echo phutil_console_format(
-- 
2.12.2

With this applied, testing both the fresh repo with a single "empty" commit (--allow-empty):

 ✓  ikey@solus-bdw  ~/Solus  rm -rf luminance-hdr 
 ✓  ikey@solus-bdw  ~/Solus  git clone ssh://vcs@dev.solus-project.com/source/luminance-hdr.git
Cloning into 'luminance-hdr'...
remote: Counting objects: 2, done.
remote: Total 2 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (2/2), done.
 ✓  ikey@solus-bdw  ~/Solus  cd luminance-hdr
 ✓  ikey@solus-bdw  …/Solus/luminance-hdr   master  arc patch D38 --trace
 ARGV  '/usr/share/php/arcanist/bin/../scripts/arcanist.php' 'patch' 'D38' '--trace'
 LOAD  Loaded "phutil" from "/usr/share/php/libphutil/src".
 LOAD  Loaded "arcanist" from "/usr/share/php/arcanist/src".
Config: Reading user configuration file "/home/ikey/.arcrc"...
Config: Did not find system configuration at "/etc/arcconfig".
Working Copy: Unable to find .arcconfig in any of these locations: /home/ikey/Solus/luminance-hdr/.arcconfig.
Working Copy: Path "/home/ikey/Solus/luminance-hdr" is part of `git` working copy "/home/ikey/Solus/luminance-hdr".
Working Copy: Project root is at "/home/ikey/Solus/luminance-hdr".
Config: Did not find local configuration at "/home/ikey/Solus/luminance-hdr/.git/arc/config".
>>> [0] <conduit> differential.querydiffs() <bytes = 73>
>>> [1] <http> https://dev.solus-project.com/api/differential.querydiffs
<<< [1] <http> 247,800 us
<<< [0] <conduit> 248,138 us
>>> [2] <conduit> user.whoami() <bytes = 117>
>>> [3] <http> https://dev.solus-project.com/api/user.whoami
<<< [3] <http> 132,382 us
<<< [2] <conduit> 132,539 us
>>> [4] <conduit> differential.querydiffs() <bytes = 154>
>>> [5] <http> https://dev.solus-project.com/api/differential.querydiffs
<<< [5] <http> 668,138 us
<<< [4] <conduit> 668,267 us
>>> [6] <exec> $ git symbolic-ref --quiet HEAD
<<< [6] <exec> 3,798 us
>>> [7] <exec> $ git rev-parse --symbolic-full-name 'master'@{upstream}
<<< [7] <exec> 3,613 us
>>> [8] <exec> $ git --version
<<< [8] <exec> 3,515 us
>>> [9] <exec> $ git ls-remote --get-url 'origin'
<<< [9] <exec> 3,551 us
>>> [10] <conduit> repository.query() <bytes = 231>
>>> [11] <http> https://dev.solus-project.com/api/repository.query
<<< [11] <http> 146,756 us
<<< [10] <conduit> 146,871 us
>>> [12] <exec> $ git diff --no-ext-diff --no-textconv --submodule=short --raw 'HEAD' --
>>> [13] <exec> $ git ls-files --others --exclude-standard
<<< [13] <exec> 4,310 us
<<< [12] <exec> 5,091 us
>>> [14] <exec> $ git diff-files --name-only
<<< [14] <exec> 3,782 us
>>> [15] <exec> $ git show -s --format='%H' '4b825dc642cb6eb9a060e54bf8d69288fbee4904' --
<<< [15] <exec> 3,929 us
>>> [16] <exec> $ git symbolic-ref --quiet HEAD
<<< [16] <exec> 3,586 us
>>> [17] <exec> $ git rev-parse --verify 'arcpatch-D38'
<<< [17] <exec> 3,526 us
>>> [18] <exec> $ git branch 'arcpatch-D38'
<<< [18] <exec> 3,893 us
>>> [19] <exec> $ git checkout 'arcpatch-D38'
<<< [19] <exec> 4,391 us
Created and checked out branch arcpatch-D38.
>>> [20] <exec> $ git show -s --format='%H' '4b825dc642cb6eb9a060e54bf8d69288fbee4904' --
<<< [20] <exec> 3,666 us
>>> [21] <exec> $ git apply --whitespace nowarn --index --reject -- '/tmp/3fxe9tok78g0sksc/6796-0sr8Ja'
Checking patch pspec_x86_64.xml...
Checking patch package.yml...
Checking patch Makefile...
Applied patch pspec_x86_64.xml cleanly.
Applied patch package.yml cleanly.
Applied patch Makefile cleanly.
<<< [21] <exec> 4,160 us
>>> [22] <exec> $ git submodule update --init --recursive
<<< [22] <exec> 30,038 us
>>> [23] <conduit> differential.getcommitmessage() <bytes = 148>
>>> [24] <http> https://dev.solus-project.com/api/differential.getcommitmessage
<<< [24] <http> 167,531 us
<<< [23] <conduit> 167,692 us
>>> [25] <exec> $ git commit -a --author='Devil505 <devil505linux@gmail.com>' -F - --no-verify
<<< [25] <exec> 177,378 us
 OKAY  Successfully committed patch.
 ✓  ikey@solus-bdw  …/Solus/luminance-hdr   arcpatch-D38 

Thank you for your time - and thank you for Phabricator :)

Event Timeline

Sidenote, it does turn out that in any instance, this will require some kind of empty commit for HEAD to exist, i.e. Repo constructed - but this change at least allows the empty commit to work.

At this time I'm presently unable to sign a CLA (apologies) due to employment situation, however what I can do is make the following diff Public Domain and relinquish any claims to it, should Phacility wish to correct this behaviour in upstream Phabricator.

I can't imagine this mattering here, but for future cases, we'd prefer you not do this. The best case scenario is that we save a few minutes producing a similar patch. The worst case scenario is that you didn't read your employment contract carefully, it contains a clause which blanket assigns all your IP to your employer, that you don't have the ability to release the patch as public domain, and that your employer later sues us.

If they do, they can at least reasonably argue that we were insufficiently diligent in accepting your claim that you have permission to release the change into the public domain, because, e.g., our own documentation makes it clear that we are aware that IP assignment agreements are common in employment contracts (see: https://secure.phabricator.com/book/phabcontrib/article/cla/). I can't really imagine this being a winning argument, but the upside is so small that we'd prefer to err heavily on the side of caution with CLA issues.

The works here are on behalf of Solus, for the Solus infrastructure, and not that of my employer, and as such have blanket "own time approval" for the umbrella "Solus Project". This much I can do. Signing a CLA of any description for any purpose is what would entangle employers, something I cannot do.

Edit: Also to make context clear and reduce perceived complexity, the diff should be viewed therefore as an idea, not the solution, as it solves half a problem, not a complete one (still requires some kind of HEAD) as demonstrated by close+merge into other issue.