Commit Graph

37 Commits

Author SHA1 Message Date
Junio C Hamano
07601b5b36 Merge branch 'ma/worktree-cleanups'
Code clean-up.

* ma/worktree-cleanups:
  worktree: use skip_prefix to parse target
  worktree: rename copy-pasted variable
  worktree: update renamed variable in comment
  worktree: inline `worktree_ref()` into its only caller
  wt-status: introduce wt_status_state_free_buffers()
  wt-status: print to s->fp, not stdout
  wt-status: replace sha1 mentions with oid
2020-10-05 14:01:52 -07:00
Martin Ågren
ef2d5547fa worktree: inline worktree_ref() into its only caller
We have `strbuf_worktree_ref()`, which works on a strbuf, and a wrapper
for it, `worktree_ref()` which returns a string. We even make this
wrapper available through worktree.h. But it only has a single caller,
sitting right next to it in worktree.c.

Just inline the wrapper into its only caller. This means the caller can
quite naturally reuse a single strbuf. We currently achieve something
similar by having a static strbuf in the wrapper.

Signed-off-by: Martin Ågren <martin.agren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-09-27 14:21:47 -07:00
Eric Sunshine
b214ab5aa5 worktree: teach "repair" to fix outgoing links to worktrees
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-31 11:47:45 -07:00
Eric Sunshine
bdd1f3e4da worktree: teach "repair" to fix worktree back-links to main worktree
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-31 11:47:45 -07:00
Eric Sunshine
03f2465bb1 worktree: drop get_worktrees() unused 'flags' argument
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-22 10:31:15 -07:00
Eric Sunshine
d9c54c2bbf worktree: drop get_worktrees() special-purpose sorting option
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-22 10:30:29 -07:00
Eric Sunshine
bb4995fc3f worktree: add utility to find worktree by pathname
find_worktree() employs heuristics to match user provided input -- which
may be a pathname or some sort of shorthand -- with an actual worktree.
Although this convenience allows a user to identify a worktree with
minimal typing, the black-box nature of these heuristics makes it
potentially difficult for callers which already know the exact path of a
worktree to be confident that the correct worktree will be returned for
any specific pathname (particularly a relative one), especially as the
heuristics are enhanced and updated.

Therefore, add a companion function, find_worktree_by_path(), which
deterministically identifies a worktree strictly by pathname with no
interpretation and no magic matching.

Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-02-24 13:04:30 -08:00
Eric Sunshine
a80c4c2214 worktree: improve find_worktree() documentation
Do a better job of explaining that find_worktree()'s main purpose is to
locate a worktree based upon input from a user which may be some sort of
shorthand for identifying a worktree rather than an actual path. For
instance, one shorthand a user can use to identify a worktree is by
unique path suffix (i.e. given worktrees at paths "foo/bar" and
"foo/baz", the latter can be identified simply as "baz"). The actual
heuristics find_worktree() uses to select a worktree may be expanded in
the future (for instance, one day it may allow worktree selection by
<id> of the .git/worktrees/<id>/ administrative directory), thus the
documentation does not provide a precise description of how matching is
performed, instead leaving it open-ended to allow for future
enhancement.

While at it, drop mention of the non-NULL requirement of `prefix` since
NULL has long been allowed. For instance, prefix_filename() has
explicitly allowed NULL since 116fb64e43 (prefix_filename: drop length
parameter, 2017-03-20), and find_worktree() itself since e4da43b1f0
(prefix_filename: return newly allocated string, 2017-03-20).

Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-02-24 13:04:04 -08:00
Denton Liu
ad6dad0996 *.[ch]: manually align parameter lists
In previous patches, extern was mechanically removed from function
declarations without care to formatting, causing parameter lists to be
misaligned. Manually format changed sections such that the parameter
lists should be realigned.

Viewing this patch with 'git diff -w' should produce no output.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-05-05 15:20:10 +09:00
Denton Liu
b199d7147a *.[ch]: remove extern from function declarations using sed
There has been a push to remove extern from function declarations.
Finish the job by removing all instances of "extern" for function
declarations in headers using sed.

This was done by running the following on my system with sed 4.2.2:

    $ git ls-files \*.{c,h} |
        grep -v ^compat/ |
        xargs sed -i'' -e 's/^\(\s*\)extern \([^(]*([^*]\)/\1\2/'

Files under `compat/` are intentionally excluded as some are directly
copied from external sources and we should avoid churning them as much
as possible.

Then, leftover instances of extern were found by running

    $ git grep -w -C3 extern \*.{c,h}

and manually checking the output. No other instances were found.

Note that the regex used specifically excludes function variables which
_should_ be left as extern.

Not the most elegant way to do it but it gets the job done.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-05-05 15:20:08 +09:00
Denton Liu
554544276a *.[ch]: remove extern from function declarations using spatch
There has been a push to remove extern from function declarations.
Remove some instances of "extern" for function declarations which are
caught by Coccinelle. Note that Coccinelle has some difficulty with
processing functions with `__attribute__` or varargs so some `extern`
declarations are left behind to be dealt with in a future patch.

This was the Coccinelle patch used:

	@@
	type T;
	identifier f;
	@@
	- extern
	  T f(...);

and it was run with:

	$ git ls-files \*.{c,h} |
		grep -v ^compat/ |
		xargs spatch --sp-file contrib/coccinelle/noextern.cocci --in-place

Files under `compat/` are intentionally excluded as some are directly
copied from external sources and we should avoid churning them as much
as possible.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-05-05 15:20:06 +09:00
Junio C Hamano
e146cc97be Merge branch 'nd/per-worktree-ref-iteration'
The code to traverse objects for reachability, used to decide what
objects are unreferenced and expendable, have been taught to also
consider per-worktree refs of other worktrees as starting points to
prevent data loss.

* nd/per-worktree-ref-iteration:
  git-worktree.txt: correct linkgit command name
  reflog expire: cover reflog from all worktrees
  fsck: check HEAD and reflog from other worktrees
  fsck: move fsck_head_link() to get_default_heads() to avoid some globals
  revision.c: better error reporting on ref from different worktrees
  revision.c: correct a parameter name
  refs: new ref types to make per-worktree refs visible to all worktrees
  Add a place for (not) sharing stuff between worktrees
  refs.c: indent with tabs, not spaces
2018-11-13 22:37:26 +09:00
Nickolai Belakovski
d236f12bde worktree: rename is_worktree_locked to worktree_lock_reason
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-10-31 11:41:47 +09:00
Nickolai Belakovski
e21cc076a3 worktree: update documentation for lock_reason and lock_reason_valid
Clarify that these fields are to be considered implementation details
and direct the reader to use the is_worktree_locked function to retrieve
said information.

Signed-off-by: Nickolai Belakovski <nbelakovski@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-10-31 11:28:52 +09:00
Nguyễn Thái Ngọc Duy
ab3e1f78ae revision.c: better error reporting on ref from different worktrees
Make use of the new ref aliases to pass refs from another worktree
around and access them from the current ref store instead. This does
not change any functionality, but when a problem arises, we would like
the reported messages to mention full ref aliases, like this:

    fatal: bad object worktrees/ztemp/HEAD
    warning: reflog of 'main-worktree/HEAD' references pruned commits

instead of

    fatal: bad object HEAD
    warning: reflog of 'HEAD' references pruned commits

which does not really tell where the refs are from.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-10-22 13:32:29 +09:00
Nguyễn Thái Ngọc Duy
3a3b9d8cde refs: new ref types to make per-worktree refs visible to all worktrees
One of the problems with multiple worktree is accessing per-worktree
refs of one worktree from another worktree. This was sort of solved by
multiple ref store, where the code can open the ref store of another
worktree and has access to the ref space of that worktree.

The problem with this is reporting. "HEAD" in another ref space is
also called "HEAD" like in the current ref space. In order to
differentiate them, all the code must somehow carry the ref store
around and print something like "HEAD from this ref store".

But that is not feasible (or possible with a _lot_ of work). With the
current design, we pass a reference around as a string (so called
"refname"). Extending this design to pass a string _and_ a ref store
is a nightmare, especially when handling extended SHA-1 syntax.

So we do it another way. Instead of entering a separate ref space, we
make refs from other worktrees available in the current ref space. So
"HEAD" is always HEAD of the current worktree, but then we can have
"worktrees/blah/HEAD" to denote HEAD from a worktree named
"blah". This syntax coincidentally matches the underlying directory
structure which makes implementation a bit easier.

The main worktree has to be treated specially because well... it's
special from the beginning. So HEAD from the main worktree is
acccessible via the name "main-worktree/HEAD" instead of
"worktrees/main/HEAD" because "main" could be just another secondary
worktree.

This patch also makes it possible to specify refs from one worktree in
another one, e.g.

    git log worktrees/foo/HEAD

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-10-22 13:32:29 +09:00
Elijah Newren
ef3ca95475 Add missing includes and forward declarations
I looped over the toplevel header files, creating a temporary two-line C
program for each consisting of
  #include "git-compat-util.h"
  #include $HEADER
This patch is the result of manually fixing errors in compiling those
tiny programs.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-15 11:52:09 -07:00
Nguyễn Thái Ngọc Duy
ee6763af0a worktree remove: allow it when $GIT_WORK_TREE is already gone
"git worktree remove" basically consists of two things

- delete $GIT_WORK_TREE
- delete $GIT_DIR (which is $SUPER_GIT_DIR/worktrees/something)

If $GIT_WORK_TREE is already gone for some reason, we should be able
to finish the job by deleting $GIT_DIR.

Two notes:

- $GIT_WORK_TREE _can_ be missing if the worktree is locked. In that
  case we must not delete $GIT_DIR because the real $GIT_WORK_TREE may
  be in a usb stick somewhere. This is already handled because we
  check for lock first.

- validate_worktree() is still called because it may do more checks in
  future (and it already does something else, like checking main
  worktree, but that's irrelevant in this case)

Noticed-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-02-12 13:13:35 -08:00
Nguyễn Thái Ngọc Duy
9c620fc7a6 worktree.c: add update_worktree_location()
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-02-12 13:13:35 -08:00
Nguyễn Thái Ngọc Duy
4ddddc1f1d worktree.c: add validate_worktree()
This function is later used by "worktree move" and "worktree remove"
to ensure that we have a good connection between the repository and
the worktree. For example, if a worktree is moved manually, the
worktree location recorded in $GIT_DIR/worktrees/.../gitdir is
incorrect and we should not move that one.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-01-24 11:04:26 -08:00
brian m. carlson
0f05154c70 worktree: convert struct worktree to object_id
Convert the head_sha1 member to be head_oid instead.  This is required
to convert resolve_ref_unsafe.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-10-16 11:05:51 +09:00
Nguyễn Thái Ngọc Duy
d0c39a49cc revision.c: --all adds HEAD from all worktrees
Unless single_worktree is set, --all now adds HEAD from all worktrees.

Since reachable.c code does not use setup_revisions(), we need to call
other_head_refs_submodule() explicitly there to have the same effect on
"git prune", so that we won't accidentally delete objects needed by some
other HEADs.

A new FIXME is added because we would need something like

    int refs_other_head_refs(struct ref_store *, each_ref_fn, cb_data);

in addition to other_head_refs() to handle it, which might require

    int get_submodule_worktrees(const char *submodule, int flags);

It could be a separate topic to reduce the scope of this one.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-08-24 14:56:43 -07:00
Nguyễn Thái Ngọc Duy
fa099d2322 worktree.c: kill parse_ref() in favor of refs_resolve_ref_unsafe()
The manual parsing code is replaced with a call to refs_resolve_ref_unsafe().
The manual parsing code must die because only refs/files-backend.c
should do that.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-04-24 21:28:55 -07:00
Stefan Beller
1a248cf21d worktree: check if a submodule uses worktrees
In a later patch we want to move around the the git directory of
a submodule. Both submodules as well as worktrees are involved in
placing git directories at unusual places, so their functionality
may collide. To react appropriately to situations where worktrees
in submodules are in use, offer a new function to query the
a submodule if it uses the worktree feature.

An earlier approach:
  "Implement submodule_get_worktrees and just count them", however:
  This can be done cheaply (both in new code to write as well as run time)
  by obtaining the list of worktrees based off that submodules git
  directory. However as we have loaded the variables for the current
  repository, the values in the submodule worktree
  can be wrong, e.g.
  * core.ignorecase may differ between these two repositories
  * the ref resolution is broken (refs/heads/branch in the submodule
    resolves to the sha1 value of the `branch` in the current repository
    that may not exist or have another sha1)

The implementation here is just checking for any files in
$GIT_COMMON_DIR/worktrees for the submodule, which ought to be sufficient
if the submodule is using the current repository format, which we also
check.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-12-12 15:15:07 -08:00
Nguyễn Thái Ngọc Duy
4df1d4d466 worktree list: keep the list sorted
It makes it easier to write tests for. But it should also be good for
the user since locating a worktree by eye would be easier once they
notice this.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-11-28 13:18:51 -08:00
Nguyễn Thái Ngọc Duy
4fff1ef7ff worktree.c: get_worktrees() takes a new flag argument
This is another no-op patch, in preparation for get_worktrees() to do
optional things, like sorting.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-11-28 13:18:51 -08:00
Nguyễn Thái Ngọc Duy
346ef53058 worktree.c: add is_worktree_locked()
We need this later to avoid double locking a worktree, or unlocking one
when it's not even locked.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-13 11:53:14 -07:00
Nguyễn Thái Ngọc Duy
984ad9e56c worktree.c: add is_main_worktree()
Main worktree _is_ different. You can lock (*) a linked worktree but not
the main one, for example. Provide an API for checking that.

(*) Add the file $GIT_DIR/worktrees/xxx/locked to avoid worktree xxx
from being removed or moved.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-03 21:58:35 -07:00
Nguyễn Thái Ngọc Duy
6835314459 worktree.c: add find_worktree()
So far we haven't needed to identify an existing worktree from command
line. Future commands such as lock or move will need it. The current
implementation identifies worktrees by path (*). In future, the function
could learn to identify by $(basename $path) or tags...

(*) We could probably go cheaper with comparing inode number (and
probably more reliable than paths when unicode enters the game). But not
all systems have good inode that so let's stick to something simple for
now.

Helped-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-03 21:58:18 -07:00
Nguyễn Thái Ngọc Duy
14ace5b77b branch: do not rename a branch under bisect or rebase
The branch name in that case could be saved in rebase's head_name or
bisect's BISECT_START files. Ideally we should try to update them as
well. But it's trickier (*). Let's play safe and see if the user
complains about inconveniences before doing that.

(*) If we do it, bisect and rebase need to provide an API to rename
branches. We can't do it in worktree.c or builtin/branch.c because
when other people change rebase/bisect code, they may not be aware of
this code and accidentally break it (e.g. rename the branch file, or
refer to the branch in new files). It's a lot more work.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-22 14:09:39 -07:00
Nguyễn Thái Ngọc Duy
2e641d5825 path.c: refactor and add worktree_git_path()
do_git_path(), which is the common code for all git_path* functions, is
modified to take a worktree struct and can produce paths for any
worktree.

worktree_git_path() is the first function that makes use of this. It can
be used to write code that can examine any worktree. For example,
wt_status_get_state() will be converted using this to take
am/rebase/... state of any worktree.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-22 14:09:38 -07:00
Nguyễn Thái Ngọc Duy
750e8a60d6 worktree.c: mark current worktree
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-22 14:09:38 -07:00
Nguyễn Thái Ngọc Duy
d3b9ac07eb worktree.c: make find_shared_symref() return struct worktree *
This gives the caller more information and they can answer things like,
"is it the main worktree" or "is it the current worktree". The latter
question is needed for the "checkout a rebase branch" case later.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-22 14:09:37 -07:00
Nguyễn Thái Ngọc Duy
69dfe3b942 worktree.c: store "id" instead of "git_dir"
We can reconstruct git_dir from id quite easily. It's a bit hackier to
do the reverse.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-22 14:09:37 -07:00
Michael Rappazzo
92718b7438 worktree: add details to the worktree struct
In addition to the absolute path in the worktree struct, add the location
of the git dir, the head ref (if not detached), the head revision sha1,
whether or not head is detached, and whether or not the worktree is a
bare repo.

Signed-off-by: Michael Rappazzo <rappazzo@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-10-08 11:57:07 -07:00
Michael Rappazzo
5193490442 worktree: add a function to get worktree details
The worktree structure provided for an individual worktree includes the
absolute path of the worktree.  The fuction to get the worktree details
is a refactor of the find main/linked symref functions.

Signed-off-by: Michael Rappazzo <rappazzo@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-10-08 11:56:25 -07:00
Michael Rappazzo
ac6c561b59 worktree: add top-level worktree.c
worktree.c contains functions to work with and get information from
worktrees.  This introduction moves functions related to worktrees
from branch.c into worktree.c

Signed-off-by: Michael Rappazzo <rappazzo@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-10-02 13:07:38 -07:00