{"thread":{"id":"11148","subject":"builtin command's prefix question","startedAt":"2007-12-05T16:56:50Z","lastAt":"2007-12-06T16:04:29Z","messageCount":7,"participants":["Nguyen Thai Ngoc Duy","Junio C Hamano","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"62029","messageId":"fcaeb9bf0712050856t5d730779q82783fdb9876f41@mail.gmail.com","threadId":"11148","inReplyTo":null,"subject":"builtin command's prefix question","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2007-12-05T16:56:50Z","receivedAt":"2007-12-05T16:56:50Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Hi,\n\nI have been looking at setup_git_directory_gently() lately. From my\nunderstanding, setup_git_directory* will return a string called\n\"prefix\" that is passed to builtin commands. What is the exact meaning\nof this prefix? Correct me if I'm wrong. In early (read: no worktree)\ndays, cwd was moved to working root directory and prefix contained\nrelative path from working root directory to the original cwd. So it\nhad a few implications:\n 1. A non-empty prefix indicates cwd has been moved\n 2. If cwd is moved, it is moved to working root directory\n 3. cwd+prefix should point to the current directory at the time the\ncommand was issued (let's call it \"user cwd\")\n\nThings change a bit since the rise of worktree:\n - If GIT_DIR is set and GIT_WORK_TREE is not, prefix is relative to\nthe to-be-set-up worktree, but cwd is not changed, so point 3 is gone.\n - If GIT_DIR is not set and GiT_WORK_TREE is,\n  - and it is found that user cwd is inside a gitdir (bare repo), cwd\nhas been moved and prefix is empty, cwd+prefix no longer point to user\ncwd\n  - for other cases, cwd may not be worktree (the real worktree will\nbe setup in setup_work_tree or setup_git_directory)\n\nNow that setup_work_tree can move cwd, it should also change prefix to\nmeet point 3. But it does not.\n\nI feel dizzy now. Were my assumptions wrong? What is expected behavior\nof setup_git_directory_gently()?\n-- \nDuy\n"},{"id":"62064","messageId":"7vlk88n648.fsf@gitster.siamese.dyndns.org","threadId":"11148","inReplyTo":"fcaeb9bf0712050856t5d730779q82783fdb9876f41@mail.gmail.com","subject":"Re: builtin command's prefix question","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-05T22:12:23Z","receivedAt":"2007-12-05T22:12:23Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Nguyen Thai Ngoc Duy\" <pclouds@gmail.com> writes:\n\n> I have been looking at setup_git_directory_gently() lately. From my\n> understanding, setup_git_directory* will return a string called\n> \"prefix\" that is passed to builtin commands. What is the exact meaning\n> of this prefix?\n\nSome historical background is in order.  For a long time, we only worked\nfrom the very top of the work tree and nowhere else.  The path you get\nfrom the user on the command line was supposed to be relative to the top\nof the work tree, the user was supposed to be at the top of the work\ntree, no work from subdirectories.\n\nThis was limiting, so \"setup\" was introduced.  The commands originally\nworked only from the top would chdir up to the top of the work tree if\nit was run from a subdirectory.  This however needs adjustments to the\npaths we get from the user from the command line (or stdin for commands\nthat take such).  If we claim we work from a subdirectory, we should\ninterpret path given by the user who is in a subdirectory as relative to\nthat subdirectory.  The way to do this adjustment is to prefix the\nsubdirectory path to the path given by the user.\n\nSo, if you start a command from Documentation/ subdirectory, like this:\n\n\t$ cd Documentation\n\t$ git ls-files howto\n\ninternally, ls-files would:\n\n * Notice it was run from Documentation/ subdirectory;\n\n * cd up to the top level;\n\n * prefix \"Documentation/\" to the pathspec given by the user\n   (i.e. \"howto\"), to form \"Documentation/howto\";\n\n * Act as before, except that it strips \"Documentation/\" from its usual\n   output, to retain the illusion of working from that subdirectory.\n\nAnd prefix is \"Documentation/\" (note the trailing slash) in such a\ncase.  If you run from the top, it is NULL to signal that there is no\nneed to do any of these tricks.\n\n> ... Correct me if I'm wrong. In early (read: no worktree)\n> days, cwd was moved to working root directory and prefix contained\n> relative path from working root directory to the original cwd. So it\n> had a few implications:\n\n>  1. A non-empty prefix indicates cwd has been moved\n\nCorrect (I do not know if we care, though)\n\n>  2. If cwd is moved, it is moved to working root directory\n\nCorrect (\"we always work from top of the tree internally\" matters)\n\n>  3. cwd+prefix should point to the current directory at the time the\n> command was issued (let's call it \"user cwd\")\n\nCorrect.\n\n> Things change a bit since the rise of worktree:\n>  - If GIT_DIR is set and GIT_WORK_TREE is not, prefix is relative to\n> the to-be-set-up worktree, but cwd is not changed, so point 3 is gone.\n>  - If GIT_DIR is not set and GiT_WORK_TREE is,\n>   - and it is found that user cwd is inside a gitdir (bare repo), cwd\n> has been moved and prefix is empty, cwd+prefix no longer point to user\n> cwd\n>   - for other cases, cwd may not be worktree (the real worktree will\n> be setup in setup_work_tree or setup_git_directory)\n\nThe intention is:\n\n * If GIT_DIR is set but not GIT_WORK_TREE (nor core.worktree in\n   config), you are either inside project.git/ directory of bare\n   repository or at the toplevel of worktree-full directory.  This has\n   been the traditional behaviour before GIT_WORK_TREE and we shouldn't\n   break the existing setups that assume this behaviour.  So in that\n   sense, with this combination:\n\n   - If the repository is bare, the value of the prefix should not\n     matter; the command that wants to look at prefix by definition\n     wants to run from a subdirectory but there is no notion of\n     \"the user directory being a subdirectory of the top of the work\n     tree\" in a bare repository;\n\n   - If the repository is not bare, the user directory _MUST_ be at the\n     top of the work tree, as that is what the traditional behaviour is.\n     Anything else would break existing setups.\n\n     IOW, if you use GIT_DIR and still want to run from a subdirectory\n     of the worktree, you must have either GIT_WORK_TREE or\n     core.worktree to tell where the top of the worktree is, and if you\n     don't, then you must be at the top.\n\n   So the right thing to do in this case is not going anywhere and using\n   prefix=NULL.\n\n * I would say it is a misconfiguration if GIT_DIR is not set and\n   GIT_WORK_TREE is, as the sole purpose of GIT_WORK_TREE is so that you\n   can work from a subdirectory when you set GIT_DIR.  I may be missing\n   an obvious use case that this is useful, but I do not think of any.\n   Dscho may be able to correct me on this, as he fixed up the original\n   work tree series that was even messier quite a bit during the last\n   round.\n"},{"id":"62071","messageId":"7vk5nsloa8.fsf@gitster.siamese.dyndns.org","threadId":"11148","inReplyTo":"7vlk88n648.fsf@gitster.siamese.dyndns.org","subject":"Re: builtin command's prefix question","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-05T23:22:55Z","receivedAt":"2007-12-05T23:22:55Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n>  * I would say it is a misconfiguration if GIT_DIR is not set and\n>    GIT_WORK_TREE is, as the sole purpose of GIT_WORK_TREE is so that you\n>    can work from a subdirectory when you set GIT_DIR.  I may be missing\n>    an obvious use case that this is useful, but I do not think of any.\n>    Dscho may be able to correct me on this, as he fixed up the original\n>    work tree series that was even messier quite a bit during the last\n>    round.\n\nI had a short discussion with Dscho on this.  One scenario that was\nbrought up was this.\n\nYou have a work tree of mixed contents that logically belong to\nseparate repository.  Think $HOME/.?*, and tracking .vimrc and\n.pinerc as separate \"projects\".  You have $HOME/gits/vim.git and\n$HOME/gits/pine.git bare-looking repositories.\n\nThe \"kosher\" way of doing this might be:\n\n        $ cd $HOME\n        $ GIT_WORK_TREE=$HOME; export GIT_WORK_TREE\n        $ edit .vimrc\n        $ GIT_DIR=gits/vim.git git commit .vimrc\n        $ edit .pinerc\n        $ GIT_DIR=gits/pine.git git commit .pinerc\n\nHowever, if we define setup() to behave this way when GIT_DIR is not\ndefined and GIT_WORK_TREE is:\n\n (1) internally pretend as if GIT_DIR was specified to be the\n     directory where the command was started from (iow, do getcwd()\n     once upon startup);\n\n (2) chdir to GIT_WORK_TREE (which means \"callers of setup() always\n     run from the top of the work tree\");\n\n (3) set prefix to NULL;\n\nThen this workflow becomes possible:\n\n\t$ cd $HOME\n        $ GIT_WORK_TREE=$HOME; export GIT_WORK_TREE\n\t$ edit .vimrc .pinerc\n        $ cd $HOME/gits/vimrc.git && git commit .vimrc\n        $ cd $HOME/gits/pinerc.git && git commit .pinerc\n\nI am not convinced this is giving any natural user experience, nor an\nalternative:\n\n\t$ cd $HOME\n        $ GIT_WORK_TREE=$HOME; export GIT_WORK_TREE\n        $ cd $HOME/gits/vimrc.git\n\t$ edit $HOME/.vimrc\n        $ git commit .vimrc\n        $ cd $HOME/gits/pinerc.git\n\t$ edit $HOME/.pinerc\n        $ git commit .pinerc\n\nWhile I still think the combination is simply crazy and does not make\nany sense, if enough users on the list agrees that it makes sense, I\nwouldn't mind setup() did (1) to (3) mentioned above.  The alternative\nis simply to declare GIT_WORK_TREE without GIT_DIR is a nonsense and\neither error error out or ignore GIT_WORK_TREE, which might be easier to\nexplain to people.\n\nOpinions?\n"},{"id":"62073","messageId":"7v8x48lnce.fsf@gitster.siamese.dyndns.org","threadId":"11148","inReplyTo":"7vk5nsloa8.fsf@gitster.siamese.dyndns.org","subject":"Re: builtin command's prefix question","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-05T23:43:13Z","receivedAt":"2007-12-05T23:43:13Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> I am not convinced this is giving any natural user experience, nor an\n> alternative:\n>\n>       $ cd $HOME\n>       $ GIT_WORK_TREE=$HOME; export GIT_WORK_TREE\n>       $ cd $HOME/gits/vimrc.git\n>       $ edit $HOME/.vimrc\n>       $ git commit .vimrc\n>       $ cd $HOME/gits/pinerc.git\n>       $ edit $HOME/.pinerc\n>       $ git commit .pinerc\n>\n> While I still think the combination is simply crazy and does not make\n> any sense, if enough users on the list agrees that it makes sense, I\n> wouldn't mind setup() did (1) to (3) mentioned above.  The alternative\n> is simply to declare GIT_WORK_TREE without GIT_DIR is a nonsense and\n> either error error out or ignore GIT_WORK_TREE, which might be easier to\n> explain to people.\n>\n> Opinions?\n\nSide note.\n\nBy saying the above, I do not mean it is nonsense to try supporting a\nwork tree that is an overlay of disjoint set of work tree files from\nmultiple repositories/projects.  I do think it is a worthwhile goal to\nsupport such a layout.\n\nWhat I do not like is the way the ugly workaround does it, by\nencouraging (rather, requiring) to issue git commands from a location\nthat is completely separate from the actual editing of the content\nhappens.\n\nAn independent issue of supporting such a overlayed work tree layout is\nwhat to do with .gitignore files.  I think, especially with the recent\naddition of --exclude-standard to ls-files and setup_standard_excludes()\nin dir.c, we could have a per repository configuration that names the\nper repository exclude files, so that .gitignore-vim and .gitignore-pine\ncan co-exist in $HOME, each excluding everything other than the\nproject's own files.\n"},{"id":"62155","messageId":"fcaeb9bf0712060726r383c3a36j798a439b9dbb0cae@mail.gmail.com","threadId":"11148","inReplyTo":"7vlk88n648.fsf@gitster.siamese.dyndns.org","subject":"Re: builtin command's prefix question","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2007-12-06T15:26:29Z","receivedAt":"2007-12-06T15:26:29Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Dec 6, 2007 5:12 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> The intention is:\n>\n>  * If GIT_DIR is set but not GIT_WORK_TREE (nor core.worktree in\n>    config), you are either inside project.git/ directory of bare\n>    repository or at the toplevel of worktree-full directory.  This has\n>    been the traditional behaviour before GIT_WORK_TREE and we shouldn't\n>    break the existing setups that assume this behaviour.  So in that\n>    sense, with this combination:\n>\n>    - If the repository is bare, the value of the prefix should not\n>      matter; the command that wants to look at prefix by definition\n>      wants to run from a subdirectory but there is no notion of\n>      \"the user directory being a subdirectory of the top of the work\n>      tree\" in a bare repository;\n>\n>    - If the repository is not bare, the user directory _MUST_ be at the\n>      top of the work tree, as that is what the traditional behaviour is.\n>      Anything else would break existing setups.\n>\n>      IOW, if you use GIT_DIR and still want to run from a subdirectory\n>      of the worktree, you must have either GIT_WORK_TREE or\n>      core.worktree to tell where the top of the worktree is, and if you\n>      don't, then you must be at the top.\n>\n>    So the right thing to do in this case is not going anywhere and using\n>    prefix=NULL.\n\nYou are right. It is quite obvious from the code. No idea why I had\nthat in my mind.\n\n>  * I would say it is a misconfiguration if GIT_DIR is not set and\n>    GIT_WORK_TREE is, as the sole purpose of GIT_WORK_TREE is so that you\n>    can work from a subdirectory when you set GIT_DIR.  I may be missing\n>    an obvious use case that this is useful, but I do not think of any.\n>    Dscho may be able to correct me on this, as he fixed up the original\n>    work tree series that was even messier quite a bit during the last\n>    round.\n\nOn Dec 6, 2007 6:22 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> However, if we define setup() to behave this way when GIT_DIR is not\n> defined and GIT_WORK_TREE is:\n>\n>  (1) internally pretend as if GIT_DIR was specified to be the\n>      directory where the command was started from (iow, do getcwd()\n>      once upon startup);\n>\n>  (2) chdir to GIT_WORK_TREE (which means \"callers of setup() always\n>      run from the top of the work tree\");\n>\n>  (3) set prefix to NULL;\n\n(1) is fine by me, even if it goes up to find a gitdir. But (3), no,\nprefix should be set as relative path from worktree top directory to\nuser current directory, not NULL.\n\n> ...\n> While I still think the combination is simply crazy and does not make\n> any sense, if enough users on the list agrees that it makes sense, I\n> wouldn't mind setup() did (1) to (3) mentioned above.  The alternative\n> is simply to declare GIT_WOR+1 on whatever way that makes worktree less complicated. so your alternative ++K_TREE without GIT_DIR is a nonsense and\n> either error error out or ignore GIT_WORK_TREE, which might be easier to\n> explain to people.\n\nI don't use either way you mentioned. So no comment here. But again,\nno (3) please.\n-- \nDuy\n"},{"id":"62157","messageId":"Pine.LNX.4.64.0712061547070.27959@racer.site","threadId":"11148","inReplyTo":"fcaeb9bf0712060726r383c3a36j798a439b9dbb0cae@mail.gmail.com","subject":"Re: builtin command's prefix question","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-12-06T15:48:02Z","receivedAt":"2007-12-06T15:48:02Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 6 Dec 2007, Nguyen Thai Ngoc Duy wrote:\n\n> On Dec 6, 2007 6:22 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> > However, if we define setup() to behave this way when GIT_DIR is not \n> > defined and GIT_WORK_TREE is:\n> >\n> >  (1) internally pretend as if GIT_DIR was specified to be the\n> >      directory where the command was started from (iow, do getcwd()\n> >      once upon startup);\n> >\n> >  (2) chdir to GIT_WORK_TREE (which means \"callers of setup() always\n> >      run from the top of the work tree\");\n> >\n> >  (3) set prefix to NULL;\n> \n> (1) is fine by me, even if it goes up to find a gitdir. But (3), no, \n> prefix should be set as relative path from worktree top directory to \n> user current directory, not NULL.\n\nIf you expect \"git <command> <filespec>\" to work correctly from GIT_DIR, \nyou will _have_ to set the prefix to NULL.\n\nCiao,\nDscho\n"},{"id":"62161","messageId":"7v63zbg67m.fsf@gitster.siamese.dyndns.org","threadId":"11148","inReplyTo":"Pine.LNX.4.64.0712061547070.27959@racer.site","subject":"Re: builtin command's prefix question","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-06T16:04:29Z","receivedAt":"2007-12-06T16:04:29Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> On Thu, 6 Dec 2007, Nguyen Thai Ngoc Duy wrote:\n>\n>> On Dec 6, 2007 6:22 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> > However, if we define setup() to behave this way when GIT_DIR is not \n>> > defined and GIT_WORK_TREE is:\n>> >\n>> >  (1) internally pretend as if GIT_DIR was specified to be the\n>> >      directory where the command was started from (iow, do getcwd()\n>> >      once upon startup);\n>> >\n>> >  (2) chdir to GIT_WORK_TREE (which means \"callers of setup() always\n>> >      run from the top of the work tree\");\n>> >\n>> >  (3) set prefix to NULL;\n>> \n>> (1) is fine by me, even if it goes up to find a gitdir. But (3), no, \n>> prefix should be set as relative path from worktree top directory to \n>> user current directory, not NULL.\n>\n> If you expect \"git <command> <filespec>\" to work correctly from GIT_DIR, \n> you will _have_ to set the prefix to NULL.\n\nThat depends on the definition of \"correctly\".\n\nAs I said, I think the above \"rule-looking things\" implement an insane\nbehaviour where you are in one directory, and use that <filespec> to\nname things relative to some other directory whose location is\ncompletely unrelated to the directory you are in.  IOW, not a good set\nof rules, and I do not necessarily agree with the statement that says\nsuch a behaviour is working \"correctly from GIT_DIR\".\n"}]}