Re: [long] worktree setup cases

3 messages, 3 authors, 2016-06-15 · open the first message on its own page

Re: [long] worktree setup cases

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:49:49

Nguyen Thai Ngoc Duy [off-list ref] writes:
Assumptions:

1. When .git is a file and contains a relative path, I assume it is
   relative to .git file's parent directory.  read_gitfile_gently()
   function will make the path absolute, but it depends on (maybe
   wrong) cwd.
Ok.  I agree that a regular file .git that has "gitdir: ../there" in it
should be naming "there" directory next to the directory .git lives in.
It is insane for it to take $(cwd) into account.
There are a few factors that affect gitdir/worktree/cwd/prefix setup.
Those are:

 - GIT_DIR (or --git-dir)
 - GIT_WORK_TREE (or --work-tree)
 - core.worktree
 - .git is a file pointing to real .git directory
 - Bare repo

So there are 2^5 = 32 cases in total.
Hmm, why is core.worktree separate from the second item?  In any case, the
three mechanisms to specify the working tree should only be in effect when
GIT_DIR/--git-dir is used, so the above are not orthogonal, and the total
count should be smaller than 32 cases.
The following questions must be answered for each case:

0. What setup function handles that case?
1. Is worktree available?
2. Where is new cwd? Is it at worktree root?
3. Prefix?
4. Is (relative) $GIT_DIR accessible from current cwd?
5. What if original cwd is outside worktree, or new cwd if it's not at
   worktree root?
All good questions to ask, except for the last one which I cannot quite
parse.
Table of Contents
=================
1 Cases
    1.1 Case 0, 8
    1.2 Case 1, 4, 5, 9, 12, 13
        1.2.1 cwd outside worktree
    1.3 Case 2, 10
    1.4 Case 3, 6, 7, 11, 14, 15
        1.4.1 cwd outside worktree
    1.5 Case 16, 24
    1.6 Case 17, 20, 21, 25, 28, 29
        1.6.1 cwd outside worktree
    1.7 Case 18, 26
    1.8 Case 19, 22, 23, 27, 30, 31


1 Cases
~~~~~~~~

Case#  Bare  .git-file  core.worktree  GIT_DIR  GIT_WORK_TREE
0      0     0          0              0        0
8      0     1          0              0        0
Ok.
1      0     0          0              0        1
4      0     0          1              0        0
5      0     0          1              0        1
9      0     1          0              0        1
12     0     1          1              0        0
13     0     1          1              0        1
How does it make sense to have GIT_WORK_TREE without GIT_DIR?  Without
GIT_DIR, we will run repository discovery, which means we will always go
up to find a .git dir, and the reason for doing that is because we want to
also work in a subdirectory of a working tree (the very original git never
worked from anywhere other than the root level of the working tree).  By
definition, the root of the working tree is the same as in cases 0/8.
2      0     0          0              1        0
10     0     1          0              1        0
If you set GIT_DIR, we do no discovery, so git will work only from the
root level of the working tree (or bare repository operation) if you do
not tell us where the working tree is.
3      0     0          0              1        1
6      0     0          1              1        0
7      0     0          1              1        1
11     0     1          0              1        1
14     0     1          1              1        0
15     0     1          1              1        1
Without discovery, we know where the root level of the working tree is,
and we know where the repository is, because you told us.  The answers to
questions 1-5, i.e. semantics observable by the end user, should be the
same as case 0/8 even though the internal codepath to achieve that,
i.e. question 0, may be different.
16     1     0          0              0        0
...
31     1     1          1              1        1
Shouldn't all of these 16 be the same, if the repository is bare?  What is
your definition of bareness?  core.bare?  In any case we should say "you
are using a bare repository, there is no working tree" and cwd shouldn't
change in these cases.  They are all bare and there is no working tree.

Alternatively, you could give precedence to core.worktree and friends, in
which case these can go to the other categories in your description,
ignoring core.bare settings.  For example, 31 explicitly specifies where
the .git directory and the working tree are, which would fall into the
same category as 3,6,7,11,14,15.

Either way is fine.
1.1 Case 0, 8
==============

The most used case, nothing special is set.

0. setup_discovered_git_dir()
1. work tree is .git dir's parent directory
2. cwd is at worktree root, i.e. .git dir's parent dir
3. prefix is calculated from original cwd
4. git_dir is set to ".git" (#0) or according to .git file, made
   absolute (#8)
5. N/A

TODO: turn git_dir to relative in #8
Ok.
1.2 Case 1, 4, 5, 9, 12, 13
As I said already, isn't this a nonsense combination you should error out?
1.3 Case 2, 10
===============

0. setup_explicit_git_dir()
1. worktree is set at cwd for legacy reason
2. cwd is unchanged
3. prefix is NULL
4. git_dir is set according to GIT_DIR (#2) or according to .git file,
   made absolute (#10)

TODO: turn git_dir to relative path

Note on #10: setup_git_env() is used to read .git file
Ok.
1.4 Case 3, 6, 7, 11, 14, 15
=============================

Another normal case where worktree is at an unsual case.

0. setup_explicit_git_dir()
1. worktree is set according to GIT_WORK_TREE (#3, #7, #11, #15) or
   core.worktree (#6, #14)
2. cwd is moved to worktree root dir if original cwd is inside
   worktree
3. prefix is calculated if original cwd is inside worktree
4. git_dir is set to GIT_DIR (#3, #6, #7) or according to .git file,
   made absolute (#11, #14, #15)

TODO: if GIT_DIR is relative, it is assumed relative to original cwd,
so it breaks because cwd now is changed. Right now this does not
happen because git_dir is turned absolute. Although it's better to be
relative.

TODO: turn git_dir to relative in #11, #14, #15

FIXME on #11, #14, #15: setup_git_env() is used to read .git file. cwd
by that time is worktree root, not .git's parent dir anymore.
Ok.
1.4.1 cwd outside worktree
---------------------------

cwd is left unchanged, prefix is NULL, which is sensible for full tree
operations. is_inside_work_tree() returns 0, operations that require
worktree should check and error out.

TODO: File path output however may not be what user expected because
it will be relative to worktree root, not original cwd.
This is operating out of bounds of the original design criteria; we
probably do not error out now, which is an original bug, but I understand
that you are trying to enhance this to reach into a submodule repository
and its working tree from its superproject.  As long as we can make such
an enhancement in a way that produces sensible and consistent output, that
kind of change would be fine.

I suspect that you would need to pass in "make the path relative to this"
using some means that do not exist in the current structure of the code.

Also I suspect that for the purpose of your enhancement, the first three
lines of this paragraph would not be true.  Think of a case where you are
at the superproject level and running a recursive grep into its submodule
at "nitfol", that has contents recorded at the path "xyzzy/frotz.txt".

If you keep cwd unchanged, the path appears at nitfol/xyzzy/frotz.txt in
the working tree from the end user's point of view, so you need to pass
"nitfol/" as a different kind of "prefix" that needs to be used to modify
the path recorded in the contents tracked by the submodule.  The grep
running in the submodule will read xyzzy/frotz.txt from the index (which
is how it notices which paths are of interest), use the "nitfol/" prefix
to turn it into a path in the working tree, read from that file and report
hits.  This is an example of an operation that clearly require a working
tree, and does not have to error out.

Alternatively, if you move cwd to the top of the working tree of the
submodule, you would still need to pass "nitfol/" prefix, but it needs to
be used only in the output phase.  The grep running in the submodule will
read xyzzy/frotz.txt from the index (which is how it notices which paths
are of interest), read from the file in the working tree (relative to cwd
which now is at the root level of the submodule), and use "nitfol/" as
output prefix when reporting.

Re: [long] worktree setup cases

From: Nguyen Thai Ngoc Duy <hidden>
Date: 2016-06-15 22:49:50

On Thu, Oct 21, 2010 at 4:00 AM, Junio C Hamano [off-list ref] wrote:
quoted
There are a few factors that affect gitdir/worktree/cwd/prefix setup.
Those are:

 - GIT_DIR (or --git-dir)
 - GIT_WORK_TREE (or --work-tree)
 - core.worktree
 - .git is a file pointing to real .git directory
 - Bare repo

So there are 2^5 = 32 cases in total.
Hmm, why is core.worktree separate from the second item?
It's how the code does it. GIT_WORK_TREE can be detected early, when
cwd has not been moved. When core.worktree is found, cwd could be
somewhere. I need to separate those cases to make sure cwd is not
misused after it's been moved.
In any case, the
three mechanisms to specify the working tree should only be in effect when
GIT_DIR/--git-dir is used, so the above are not orthogonal, and the total
count should be smaller than 32 cases.
Good to hear. I forgot that GIT_DIR must be set for the three
mechanisms in effect.
quoted
The following questions must be answered for each case:

0. What setup function handles that case?
1. Is worktree available?
2. Where is new cwd? Is it at worktree root?
3. Prefix?
4. Is (relative) $GIT_DIR accessible from current cwd?
5. What if original cwd is outside worktree, or new cwd if it's not at
   worktree root?
All good questions to ask, except for the last one which I cannot quite
parse.
Skip "or new cwd... worktree root" part.
quoted
1 Cases
~~~~~~~~

Case#  Bare  .git-file  core.worktree  GIT_DIR  GIT_WORK_TREE
0      0     0          0              0        0
8      0     1          0              0        0
Ok.
quoted
1      0     0          0              0        1
4      0     0          1              0        0
5      0     0          1              0        1
9      0     1          0              0        1
12     0     1          1              0        0
13     0     1          1              0        1
How does it make sense to have GIT_WORK_TREE without GIT_DIR?  Without
GIT_DIR, we will run repository discovery, which means we will always go
up to find a .git dir, and the reason for doing that is because we want to
also work in a subdirectory of a working tree (the very original git never
worked from anywhere other than the root level of the working tree).  By
definition, the root of the working tree is the same as in cases 0/8.
OK.
quoted
2      0     0          0              1        0
10     0     1          0              1        0
If you set GIT_DIR, we do no discovery, so git will work only from the
root level of the working tree (or bare repository operation) if you do
not tell us where the working tree is.
OK
quoted
3      0     0          0              1        1
6      0     0          1              1        0
7      0     0          1              1        1
11     0     1          0              1        1
14     0     1          1              1        0
15     0     1          1              1        1
Without discovery, we know where the root level of the working tree is,
and we know where the repository is, because you told us.  The answers to
questions 1-5, i.e. semantics observable by the end user, should be the
same as case 0/8 even though the internal codepath to achieve that,
i.e. question 0, may be different.
OK too.
quoted
16     1     0          0              0        0
...
31     1     1          1              1        1
Shouldn't all of these 16 be the same, if the repository is bare?  What is
your definition of bareness?  core.bare?  In any case we should say "you
are using a bare repository, there is no working tree" and cwd shouldn't
change in these cases.  They are all bare and there is no working tree.
Better this way. Although some sanity checks can be used. Like setting
core.bare and explicitly requesting worktree is insane.
Alternatively, you could give precedence to core.worktree and friends, in
which case these can go to the other categories in your description,
ignoring core.bare settings.  For example, 31 explicitly specifies where
the .git directory and the working tree are, which would fall into the
same category as 3,6,7,11,14,15.
I don't want to ignore core.bare. If there are bare/worktree
conflicts, notify users. There are cases that a normal repo tends to
become a bare repo for just one operation. It's when "." is found a
repo, handled by setup_bare_git_dir(). In these cases, we might want
to consider core.worktree and friends again.
Either way is fine.
-- 
Duy

Re: [long] worktree setup cases

From: Enrico Weigelt <hidden>
Date: 2016-06-15 22:49:50

* Junio C Hamano [off-list ref] wrote:
If you set GIT_DIR, we do no discovery, so git will work only from the
root level of the working tree (or bare repository operation) if you do
not tell us where the working tree is.
Well, we could look at config whether it's an non-bare repo and then
lookup worktree via core.worktree (which would default to "../").


BTW: the whole discovery process IMHO should start w/ looking for 
the gitdir. Could be done this way:

a) explicitly given (via GIT_DIR or --git-dir), take this one.
b) else: recursively scan for a valid .git dir from cwd upstairs to /

Once we've found gitdir, we can look for the worktree. Again:

a) explicitly given, then take it
b) bare repo: dont have any, bail out
c) non-bare repo: look up via core.worktree (w/ default to $GIT_DIR/../)
 
Shouldn't all of these 16 be the same, if the repository is bare?  What is
your definition of bareness?  core.bare?  In any case we should say "you
are using a bare repository, there is no working tree" and cwd shouldn't
change in these cases.  They are all bare and there is no working tree.
ACK. In a bare repo, the worktree lookup will fail per definition, so
worktree operations can only run with having it explicitly given.


cu
-- 
----------------------------------------------------------------------
 Enrico Weigelt, metux IT service -- http://www.metux.de/

 phone:  +49 36207 519931  email: weigelt@metux.de
 mobile: +49 151 27565287  icq:   210169427         skype: nekrad666
----------------------------------------------------------------------
 Embedded-Linux / Portierung / Opensource-QM / Verteilte Systeme
----------------------------------------------------------------------
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help