summaryrefslogtreecommitdiff
path: root/builtin/worktree.c
AgeCommit message (Collapse)Author
2020-09-09Merge branch 'es/worktree-repair'Junio C Hamano
"git worktree" gained a "repair" subcommand to help users recover after moving the worktrees or repository manually without telling Git. Also, "git init --separate-git-dir" no longer corrupts administrative data related to linked worktrees. * es/worktree-repair: init: make --separate-git-dir work from within linked worktree init: teach --separate-git-dir to repair linked worktrees worktree: teach "repair" to fix outgoing links to worktrees worktree: teach "repair" to fix worktree back-links to main worktree worktree: add skeleton "repair" command
2020-09-09Merge branch 'jk/worktree-check-clean-leakfix'Junio C Hamano
Leakfix. * jk/worktree-check-clean-leakfix: worktree: fix leak in check_clean_worktree()
2020-08-31worktree: teach "repair" to fix outgoing links to worktreesEric Sunshine
The .git/worktrees/<id>/gitdir file points at the location of a linked worktree's .git file. Its content must be of the form /path/to/worktree/.git (from which the location of the worktree itself can be derived by stripping the "/.git" suffix). If the gitdir file is deleted or becomes corrupted or outdated, then Git will be unable to find the linked worktree. An easy way for the gitdir file to become outdated is for the user to move the worktree manually (without using "git worktree move"). Although it is possible to manually update the gitdir file to reflect the new linked worktree location, doing so requires a level of knowledge about worktree internals beyond what a user should be expected to know offhand. Therefore, teach "git worktree repair" how to repair broken or outdated .git/worktrees/<id>/gitdir files automatically. (For this to work, the command must either be invoked from within the worktree whose gitdir file requires repair, or from within the main or any linked worktree by providing the path of the broken worktree as an argument to "git worktree repair".) Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-08-31worktree: teach "repair" to fix worktree back-links to main worktreeEric Sunshine
The .git file in a linked worktree is a "gitfile" which points back to the .git/worktrees/<id> entry in the main worktree or bare repository. If a worktree's .git file is deleted or becomes corrupted or outdated, then the linked worktree won't know how to find the repository or any of its own administrative files (such as 'index', 'HEAD', etc.). An easy way for the .git file to become outdated is for the user to move the main worktree or bare repository. Although it is possible to manually update each linked worktree's .git file to reflect the new repository location, doing so requires a level of knowledge about worktree internals beyond what a user should be expected to know offhand. Therefore, teach "git worktree repair" how to repair broken or outdated worktree .git files automatically. (For this to work, the command must be invoked from within the main worktree or bare repository, or from within a worktree which has not become disconnected from the repository -- such as one which was created after the repository was moved.) Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-08-27worktree: add skeleton "repair" commandEric Sunshine
Worktree administrative files can become corrupted or outdated due to external factors. Although, it is often possible to recover from such situations by hand-tweaking these files, doing so requires intimate knowledge of worktree internals. While information necessary to make such repairs manually can be obtained from git-worktree.txt and gitrepository-layout.txt, we can assist users more directly by teaching git-worktree how to repair its administrative files itself (at least to some extent). Therefore, add a "git worktree repair" command which attempts to correct common problems which may arise due to factors beyond Git's control. At this stage, the "repair" command is a mere skeleton; subsequent commits will flesh out the functionality. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-08-27worktree: fix leak in check_clean_worktree()Jeff King
We allocate a child_env strvec but never free its memory. Instead, let's just use the strvec that our child_process struct provides, which is cleaned up automatically when we run the command. And while we're moving the initialization of the child_process around, let's switch it to use the official init function (zero-initializing it works OK, since strvec is happy enough with that, but it sets a bad example). Signed-off-by: Jeff King <peff@peff.net> Reviewed-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-07-31strvec: rename struct fieldsJeff King
The "argc" and "argv" names made sense when the struct was argv_array, but now they're just confusing. Let's rename them to "nr" (which we use for counts elsewhere) and "v" (which is rather terse, but reads well when combined with typical variable names like "args.v"). Note that we have to update all of the callers immediately. Playing tricks with the preprocessor is hard here, because we wouldn't want to rewrite unrelated tokens. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-07-28strvec: fix indentation in renamed callsJeff King
Code which split an argv_array call across multiple lines, like: argv_array_pushl(&args, "one argument", "another argument", "and more", NULL); was recently mechanically renamed to use strvec, which results in mis-matched indentation like: strvec_pushl(&args, "one argument", "another argument", "and more", NULL); Let's fix these up to align the arguments with the opening paren. I did this manually by sifting through the results of: git jump grep 'strvec_.*,$' and liberally applying my editor's auto-format. Most of the changes are of the form shown above, though I also normalized a few that had originally used a single-tab indentation (rather than our usual style of aligning with the open paren). I also rewrapped a couple of obvious cases (e.g., where previously too-long lines became short enough to fit on one), but I wasn't aggressive about it. In cases broken to three or more lines, the grouping of arguments is sometimes meaningful, and it wasn't worth my time or reviewer time to ponder each case individually. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-07-28strvec: convert builtin/ callers away from argv_array nameJeff King
We eventually want to drop the argv_array name and just use strvec consistently. There's no particular reason we have to do it all at once, or care about interactions between converted and unconverted bits. Because of our preprocessor compat layer, the names are interchangeable to the compiler (so even a definition and declaration using different names is OK). This patch converts all of the files in builtin/ to keep the diff to a manageable size. The conversion was done purely mechanically with: git ls-files '*.c' '*.h' | xargs perl -i -pe ' s/ARGV_ARRAY/STRVEC/g; s/argv_array/strvec/g; ' and then selectively staging files with "git add builtin/". We'll deal with any indentation/style fallouts separately. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-07-28strvec: rename files from argv-array to strvecJeff King
This requires updating #include lines across the code-base, but that's all fairly mechanical, and was done with: git ls-files '*.c' '*.h' | xargs perl -i -pe 's/argv-array.h/strvec.h/' Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-07-07Merge branch 'es/get-worktrees-unsort'Junio C Hamano
API cleanup for get_worktrees() * es/get-worktrees-unsort: worktree: drop get_worktrees() unused 'flags' argument worktree: drop get_worktrees() special-purpose sorting option
2020-06-22Merge branch 'es/worktree-duplicate-paths'Junio C Hamano
The same worktree directory must be registered only once, but "git worktree move" allowed this invariant to be violated, which has been corrected. * es/worktree-duplicate-paths: worktree: make "move" refuse to move atop missing registered worktree worktree: generalize candidate worktree path validation worktree: prune linked worktree referencing main worktree path worktree: prune duplicate entries referencing same worktree path worktree: make high-level pruning re-usable worktree: give "should be pruned?" function more meaningful name worktree: factor out repeated string literal
2020-06-22worktree: drop get_worktrees() unused 'flags' argumentEric Sunshine
get_worktrees() accepts a 'flags' argument, however, there are no existing flags (the lone flag GWT_SORT_LINKED was recently retired) and no behavior which can be tweaked. Therefore, drop the 'flags' argument. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-06-22worktree: drop get_worktrees() special-purpose sorting optionEric Sunshine
Of all the clients of get_worktrees(), only "git worktree list" wants the list sorted in a very specific way; other clients simply don't care about the order. Rather than imbuing get_worktrees() with special knowledge about how various clients -- now and in the future -- may want the list sorted, drop the sorting capability altogether and make it the client's responsibility to sort the list if needed. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-06-10worktree: make "move" refuse to move atop missing registered worktreeEric Sunshine
"git worktree add" takes special care to avoid creating a new worktree at a location already registered to an existing worktree even if that worktree is missing (which can happen, for instance, if the worktree resides on removable media). "git worktree move", however, is not so careful when validating the destination location and will happily move the source worktree atop the location of a missing worktree. This leads to the anomalous situation of multiple worktrees being associated with the same path, which is expressly forbidden by design. For example: $ git clone foo.git $ cd foo $ git worktree add ../bar $ git worktree add ../baz $ rm -rf ../bar $ git worktree move ../baz ../bar $ git worktree list .../foo beefd00f [master] .../bar beefd00f [bar] .../bar beefd00f [baz] $ git worktree remove ../bar fatal: validation failed, cannot remove working tree: '.../bar' does not point back to '.git/worktrees/bar' Fix this shortcoming by enhancing "git worktree move" to perform the same additional validation of the destination directory as done by "git worktree add". While at it, add a test to verify that "git worktree move" won't move a worktree atop an existing (non-worktree) path -- a restriction which has always been in place but was never tested. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-06-10worktree: generalize candidate worktree path validationEric Sunshine
"git worktree add" checks that the specified path is a valid location for a new worktree by ensuring that the path does not already exist and is not already registered to another worktree (a path can be registered but missing, for instance, if it resides on removable media). Since "git worktree add" is not the only command which should perform such validation ("git worktree move" ought to also), generalize the the validation function for use by other callers, as well. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-06-10worktree: prune linked worktree referencing main worktree pathEric Sunshine
"git worktree prune" detects when multiple entries are associated with the same path and prunes the duplicates, however, it does not detect when a linked worktree points at the path of the main worktree. Although "git worktree add" disallows creating a new worktree with the same path as the main worktree, such a case can arise outside the control of Git even without the user mucking with .git/worktree/<id>/ administrative files. For instance: $ git clone foo.git $ git -C foo worktree add ../bar $ rm -rf bar $ mv foo bar $ git -C bar worktree list .../bar deadfeeb [master] .../bar deadfeeb [bar] Help the user recover from such corruption by extending "git worktree prune" to also detect when a linked worktree is associated with the path of the main worktree. Reported-by: Jonathan Müller <jonathanmueller.dev@gmail.com> Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-06-10worktree: prune duplicate entries referencing same worktree pathEric Sunshine
A fundamental restriction of linked working trees is that there must only ever be a single worktree associated with a particular path, thus "git worktree add" explicitly disallows creation of a new worktree at the same location as an existing registered worktree. Nevertheless, users can still "shoot themselves in the foot" by mucking with administrative files in .git/worktree/<id>/. Worse, "git worktree move" is careless[1] and allows a worktree to be moved atop a registered but missing worktree (which can happen, for instance, if the worktree is on removable media). For instance: $ git clone foo.git $ cd foo $ git worktree add ../bar $ git worktree add ../baz $ rm -rf ../bar $ git worktree move ../baz ../bar $ git worktree list .../foo beefd00f [master] .../bar beefd00f [bar] .../bar beefd00f [baz] Help users recover from this form of corruption by teaching "git worktree prune" to detect when multiple worktrees are associated with the same path. [1]: A subsequent commit will fix "git worktree move" validation to be more strict. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-06-10worktree: make high-level pruning re-usableEric Sunshine
The low-level logic for removing a worktree is well encapsulated in delete_git_dir(). However, high-level details related to pruning a worktree -- such as dealing with verbosity and dry-run mode -- are not encapsulated. Factor out this high-level logic into its own function so it can be re-used as new worktree corruption detectors are added. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-06-10worktree: give "should be pruned?" function more meaningful nameEric Sunshine
Readers of the name prune_worktree() are likely to expect the function to actually prune a worktree, however, it only answers the question "should this worktree be pruned?". Give it a name more reflective of its true purpose to avoid such confusion. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-06-08worktree: factor out repeated string literalEric Sunshine
For each worktree removed by "git worktree prune", it reports the reason for the removal. All reasons share the common prefix "Removing worktrees/%s:". As new removal reasons are added, this prefix needs to be duplicated, which is error-prone and potentially cumbersome. Therefore, factor out the common prefix. Although this change seems to increase the "sentence lego quotient", it should be reasonably safe, as the reason for removal is a distinct clause, not strictly related to the prefix. Moreover, the "worktrees" in "Removing worktrees/%s:" is a path literal which ought not be localized, so by factoring it out, we can more easily avoid exposing that path fragment to translators. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-10real_path: remove unsafe APIAlexandr Miloslavskiy
Returning a shared buffer invites very subtle bugs due to reentrancy or multi-threading, as demonstrated by the previous patch. There was an unfinished effort to abolish this [1]. Let's finally rid of `real_path()`, using `strbuf_realpath()` instead. This patch uses a local `strbuf` for most places where `real_path()` was previously called. However, two places return the value of `real_path()` to the caller. For them, a `static` local `strbuf` was added, effectively pushing the problem one level higher: read_gitfile_gently() get_superproject_working_tree() [1] https://lore.kernel.org/git/1480964316-99305-1-git-send-email-bmwill@google.com/ Signed-off-by: Alexandr Miloslavskiy <alexandr.miloslavskiy@syntevo.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-02-24worktree: don't allow "add" validation to be fooled by suffix matchingEric Sunshine
"git worktree add <path>" performs various checks before approving <path> as a valid location for the new worktree. Aside from ensuring that <path> does not already exist, one of the questions it asks is whether <path> is already a registered worktree. To perform this check, it queries find_worktree() and disallows the "add" operation if find_worktree() finds a match for <path>. As a convenience, however, find_worktree() casts an overly wide net to allow users to identify worktrees by shorthand in order to keep typing to a minimum. For instance, it performs suffix matching which, given subtrees "foo/bar" and "foo/baz", can correctly select the latter when asked only for "baz". "add" validation knows the exact path it is interrogating, so this sort of heuristic-based matching is, at best, questionable for this use-case and, at worst, may may accidentally interpret <path> as matching an existing worktree and incorrectly report it as already registered even when it isn't. (In fact, validate_worktree_add() already contains a special case to avoid accidentally matching against the main worktree, precisely due to this problem.) Avoid the problem of potential accidental matching against an existing worktree by instead taking advantage of find_worktree_by_path() which matches paths deterministically, without applying any sort of magic shorthand matching performed by find_worktree(). Reported-by: Cameron Gunnin <cameron.gunnin@synopsys.com> Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-12-01Merge branch 'pb/no-recursive-reset-hard-in-worktree-add'Junio C Hamano
"git worktree add" internally calls "reset --hard" that should not descend into submodules, even when submodule.recurse configuration is set, but it was affected. This has been corrected. * pb/no-recursive-reset-hard-in-worktree-add: worktree: teach "add" to ignore submodule.recurse config
2019-10-30worktree: teach "add" to ignore submodule.recurse configPhilippe Blain
"worktree add" internally calls "reset --hard", but if submodule.recurse is set, reset tries to recurse into initialized submodules, which makes start_command try to cd into non-existing submodule paths and die. Fix that by making sure that the call to reset in "worktree add" does not recurse. Signed-off-by: Philippe Blain <levraiphilippeblain@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-10-11Merge branch 'rs/dedup-includes'Junio C Hamano
Code cleanup. * rs/dedup-includes: treewide: remove duplicate #include directives
2019-10-11Merge branch 'bc/object-id-part17'Junio C Hamano
Preparation for SHA-256 upgrade continues. * bc/object-id-part17: (26 commits) midx: switch to using the_hash_algo builtin/show-index: replace sha1_to_hex rerere: replace sha1_to_hex builtin/receive-pack: replace sha1_to_hex builtin/index-pack: replace sha1_to_hex packfile: replace sha1_to_hex wt-status: convert struct wt_status to object_id cache: remove null_sha1 builtin/worktree: switch null_sha1 to null_oid builtin/repack: write object IDs of the proper length pack-write: use hash_to_hex when writing checksums sequencer: convert to use the_hash_algo bisect: switch to using the_hash_algo sha1-lookup: switch hard-coded constants to the_hash_algo config: use the_hash_algo in abbrev comparison combine-diff: replace GIT_SHA1_HEXSZ with the_hash_algo bundle: switch to use the_hash_algo connected: switch GIT_SHA1_HEXSZ to the_hash_algo show-index: switch hard-coded constants to the_hash_algo blame: remove needless comparison with GIT_SHA1_HEXSZ ...
2019-10-03treewide: remove duplicate #include directivesRené Scharfe
Found with "git grep '^#include ' '*.c' | sort | uniq -d". Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-08-19builtin/worktree: switch null_sha1 to null_oidbrian m. carlson
Switch the remaining use of null_sha1 to null_oid. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-08-13worktree remove: clarify error message on dirty worktreeSZEDER Gábor
To avoid data loss, 'git worktree remove' refuses to delete a worktree if it's dirty or contains untracked files. However, the error message only mentions that the worktree "is dirty", even if the worktree in question is in fact clean, but contains untracked files: $ git worktree add test-worktree Preparing worktree (new branch 'test-worktree') HEAD is now at aa53e60 Initial $ >test-worktree/untracked-file $ git worktree remove test-worktree/ fatal: 'test-worktree/' is dirty, use --force to delete it $ git -C test-worktree/ diff $ git -C test-worktree/ diff --cached $ # Huh? Where are those dirty files?! Clarify this error message to say that the worktree "contains modified or untracked files". Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Reviewed-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-06-13Merge branch 'nd/worktree-name-sanitization'Junio C Hamano
In recent versions of Git, per-worktree refs are exposed in refs/worktrees/<wtname>/ hierarchy, which means that worktree names must be a valid refname component. The code now sanitizes the names given to worktrees, to make sure these refs are well-formed. * nd/worktree-name-sanitization: worktree add: sanitize worktree names
2019-05-15worktree add: sanitize worktree namesNguyễn Thái Ngọc Duy
Worktree names are based on $(basename $GIT_WORK_TREE). They aren't significant until 3a3b9d8cde (refs: new ref types to make per-worktree refs visible to all worktrees - 2018-10-21), where worktree name could be part of a refname and must follow refname rules. Update 'worktree add' code to remove special characters to follow these rules. In the future the user will be able to specify the worktree name by themselves if they're not happy with this dumb character substitution. Reported-by: Konstantin Kharlamov <hi-angel@yandex.ru> Helped-by: Jeff King <peff@peff.net> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-04-09Merge branch 'ms/worktree-add-atomic-mkdir'Junio C Hamano
"git worktree add" used to do a "find an available name with stat and then mkdir", which is race-prone. This has been fixed by using mkdir and reacting to EEXIST in a loop. * ms/worktree-add-atomic-mkdir: worktree: fix worktree add race
2019-03-12worktree: fix worktree add raceMichal Suchanek
Git runs a stat loop to find a worktree name that's available and then does mkdir on the found name. Turn it to mkdir loop to avoid another invocation of worktree add finding the same free name and creating the directory first. Signed-off-by: Michal Suchanek <msuchanek@suse.de> Acked-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-02-22trace2:data: add trace2 hook classificationJeff Hostetler
Classify certain child processes as hooks. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-01-07worktree: allow to (re)move worktrees with uninitialized submodulesNguyễn Thái Ngọc Duy
Uninitialized submodules have nothing valueable for us to be worried about. They are just SHA-1. Let "worktree remove" and "worktree move" continue in this case so that people can still use multiple worktrees on repos with optional submodules that are never populated, like sha1collisiondetection in git.git when checked out by doc-diff script. Note that for "worktree remove", it is possible that a user initializes a submodule (*), makes some commits (but not push), then deinitializes it. At that point, the submodule is unpopulated, but the precious new commits are still in $GIT_COMMON_DIR/worktrees/<worktree>/modules/<submodule> directory and we should not allow removing the worktree or we lose those commits forever. The new directory check is added to prevent this. (*) yes they are screwed anyway by doing this since "git submodule" would add submodule.* in $GIT_COMMON_DIR/config, which is shared across multiple worktrees. But it does not mean we let them be screwed even more. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-10-31worktree: rename is_worktree_locked to worktree_lock_reasonNickolai Belakovski
A function prefixed with 'is_' would be expected to return a boolean, however this function returns a string. Signed-off-by: Nickolai Belakovski <nbelakovski@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-30worktree: delete .git/worktrees if empty after 'remove'Eric Sunshine
For cleanliness, "git worktree prune" deletes the .git/worktrees directory if it is empty after pruning is complete. For consistency, make "git worktree remove <path>" likewise delete .git/worktrees if it is empty after the removal. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-30worktree: teach 'remove' to override lock when --force given twiceEric Sunshine
For consistency with "add -f -f" and "move -f -f" which override the lock on a worktree, allow "remove -f -f" to do so, as well, as a convenience. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-30worktree: teach 'move' to override lock when --force given twiceEric Sunshine
For consistency with "add -f -f", which allows a missing but locked worktree path to be re-used, allow "move -f -f" to override a lock, as well, as a convenience. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-30worktree: teach 'add' to respect --force for registered but missing pathEric Sunshine
For safety, "git worktree add <path>" will refuse to add a new worktree at <path> if <path> is already associated with a worktree entry, even if <path> is missing (for instance, has been deleted or resides on non-mounted removable media or network share). The typical way to re-create a worktree at <path> in such a situation is either to prune all "broken" entries ("git worktree prune") or to selectively remove the worktree entry manually ("git worktree remove <path>"). However, neither of these approaches ("prune" nor "remove") is especially convenient, and they may be unsuitable for scripting when a tool merely wants to re-use a worktree if it exists or create it from scratch if it doesn't (much as a tool might use "mkdir -p" to re-use or create a directory). Therefore, teach 'add' to respect --force as a convenient way to re-use a path already associated with a worktree entry if the path is non-existent. For a locked worktree, require --force to be specified twice. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-30worktree: disallow adding same path multiple timesEric Sunshine
A given path should only ever be associated with a single registered worktree. This invariant is enforced by refusing to create a new worktree at a given path if that path already exists. For example: $ git worktree add -q --detach foo $ git worktree add -q --detach foo fatal: 'foo' already exists However, the check can be fooled, and the invariant broken, if the path is missing. Continuing the example: $ rm -fr foo $ git worktree add -q --detach foo $ git worktree list ... eadebfe [master] .../foo eadebfe (detached HEAD) .../foo eadebfe (detached HEAD) This "corruption" leads to the unfortunate situation in which the worktree can not be removed: $ git worktree remove foo fatal: validation failed, cannot remove working tree: '.../foo' does not point back to '.git/worktrees/foo' Nor can the bogus entry be pruned: $ git worktree prune -v $ git worktree list ... eadebfe [master] .../foo eadebfe (detached HEAD) .../foo eadebfe (detached HEAD) without first deleting the worktree directory manually: $ rm -fr foo $ git worktree prune -v Removing .../foo: gitdir file points to non-existent location Removing .../foo1: gitdir file points to non-existent location $ git worktree list ... eadebfe [master] or by manually deleting the worktree entry in .git/worktrees. To address this problem, upgrade "git worktree add" validation to allow worktree creation only if the given path is not already associated with an existing worktree (even if the path itself is non-existent), thus preventing such bogus worktree entries from being created in the first place. Reported-by: Jeff King <peff@peff.net> Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-30worktree: prepare for more checks of whether path can become worktreeEric Sunshine
Certain conditions must be met for a path to be a valid candidate as the location of a new worktree; for instance, the path must not exist or must be an empty directory. Although the number of conditions is small, new conditions will soon be added so factor out the existing checks into a separate function to avoid further bloating add_worktree(). Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-30worktree: generalize delete_git_dir() to reduce code duplicationEric Sunshine
prune_worktrees() and delete_git_dir() both remove worktree administrative entries from .git/worktrees, and their implementations are nearly identical. The only difference is that prune_worktrees() is also capable of removing a bogus non-worktree-related file from .git/worktrees. Simplify by extending delete_git_dir() to handle the little bit of extra functionality needed by prune_worktrees(), and drop the effectively duplicate code from the latter. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-30worktree: move delete_git_dir() earlier in file for upcoming new callersEric Sunshine
This is a pure code movement to avoid having to forward-declare the function when new callers are subsequently added. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-17worktree: add --quiet optionElia Pinto
Add the '--quiet' option to git worktree, as for the other git commands. 'add' is the only command affected by it since all other commands, except 'list', are currently silent by default. [jc: appiled trivial fix-up to keep the tests from touching outside the scratch area] Helped-by: Martin Ågren <martin.agren@gmail.com> Helped-by: Duy Nguyen <pclouds@gmail.com> Helped-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Elia Pinto <gitter.spiros@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-06-11checkout: pass the "num_matches" up to callersÆvar Arnfjörð Bjarmason
Pass the previously added "num_matches" struct value up to the callers of unique_tracking_name(). This will allow callers to optionally print better error messages in a later change. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-23Merge branch 'tg/worktree-add-existing-branch'Junio C Hamano
"git worktree add" learned to check out an existing branch. * tg/worktree-add-existing-branch: worktree: teach "add" to check out existing branches worktree: factor out dwim_branch function worktree: improve message when creating a new worktree worktree: remove extra members from struct add_opts
2018-05-08Merge branch 'sb/worktree-remove-opt-force'Junio C Hamano
"git worktree remove" learned that "-f" is a shorthand for "--force" option, just like for "git worktree add". * sb/worktree-remove-opt-force: worktree: accept -f as short for --force for removal
2018-04-30worktree: teach "add" to check out existing branchesThomas Gummerer
Currently 'git worktree add <path>' creates a new branch named after the basename of the path by default. If a branch with that name already exists, the command refuses to do anything, unless the '--force' option is given. However we can do a little better than that, and check the branch out if it is not checked out anywhere else. This will help users who just want to check an existing branch out into a new worktree, and save a few keystrokes. As the current behaviour is to simply 'die()' when a branch with the name of the basename of the path already exists, there are no backwards compatibility worries here. We will still 'die()' if the branch is checked out in another worktree, unless the --force flag is passed. Helped-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com> Reviewed-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>