Consider two branch-schemes, where the second is a subset of the first.
Suppose repositories have been cloned using the first branch scheme. Previously,
a successive update using the second branch-scheme would cause update-checkout
to fail in an attempt to query the branch-scheme about the target branch for a
repository it does not map, even though the update, given no further errors, can
be considered successful.
If 'call_quietly' fails, there is no indication as to what the failure
was, except for the exit/status code from the subprocess. This adds a
new exception type that will print out stdout/stderr from the subprocess
In addition to following current best practices for inclusive terms,
this also fixes an issue that occurs if a user has customized their
local git config to use an alternate default branch name (using
'init.defaultBranch').
If a user has set 'init.defaultBranch' in their git config to anything
other than master, the update_checkout tests fail. By setting the
sybolic-ref for HEAD after initializing the bare repo, the user's
setting will not affect the test.
In workflows featuring git worktrees, it is common for the same branch
to be in use by multiple multiple checkouts. For example, at the
moment, the "master" branches of swift-format, swift-tensorflow-apis,
and pythonkit (and the "release" branch of ninja) are indicated, in
update-checkout-config.json, by both "master" and "release/5.3". If one
has a workflow featuring git worktrees, that means that when one runs
<<update_checkout --scheme master>> in one's mainline directory and
<<update_checkout --scheme release/5.3>> in one's release/5.3 directory,
the latter will encounter failures for each of those four projects
because the branch "master" will already be checked out in the mainline
directory's worktrees and so it cannot be checked out in the
release/5.3's directory's worktrees. The error looks something like:
/path/to/swift-container/release53/swift-format failed
(ret=128): ['git', 'checkout', u'master']
fatal: 'master' is already checked out at
'/path/to/swift-container/mainline/swift-format'
/path/to/swift-container/release53/tensorflow-swift-apis failed
(ret=128): ['git', 'checkout', u'master']
fatal: 'master' is already checked out at
'/path/to/swift-container/mainline/tensorflow-swift-apis'
/path/to/swift-container/release53/pythonkit failed (ret=128):
['git', 'checkout', u'master']
fatal: 'master' is already checked out at
'/path/to/swift-container/mainline/pythonkit'
/path/to/swift-container/release53/ninja failed (ret=128):
['git', 'checkout', u'release']
fatal: 'release' is already checked out at
'/path/to/swift-container/mainline/ninja'
Here, that workflow is enabled. If <<git checkout branch_name>> fails,
for one of the projects, update_checkout falls back to getting the SHA
for the indicated branch via <<git rev-parse branch_name>> and then
checking out the SHA directly.
This commit is not meant to completely test update-checkout, but rather create
some scaffolding for testing update-checkout so we can create starter bugs to
fill out the rest of the functionality. Once we have enough testing in place, we
can start refactoring/simplifying update-checkout.
Design
------
This is just a standard python unittest test suite except that the tests expect
an environment variable (UPDATECHECKOUT_TEST_WORKSPACE_DIR) to be set that
specifies the directory that the unittests have for creating mock git repos
during setup/teardown. lit invokes the test by calling the unittests with the
environment variable set to the appropriate temporary directory.
In this temporary directory, each test creates a pristine set of "fake" remote
repos and a test-config.json file that can be passed to update-checkout to work
with these "fake" remote repos. This allows each test that we write to test
various update-checkout functionalities against a pristime set of git repos. I
choose the git clone test, just b/c it was really simple.
NOTE: One can also run the tests locally using the script
test_update_checkout.sh that uses /tmp/workspace as the workspace directory.