This environment variable can be used with GIT_DIR to
specify the toplevel working directory. When GIT_DIR is not
set this variable is ignored. As for GIT_DIR there is also
the option git --work-dir which overrides the environment
variable.
---
Missing:
Documentation update but if this feature should not get accepted..
therefore I'll wait for feedback first.
Idea:
Add some way to configure tho working directory for one repository
and set GIT_WORK_DIR automatically when GIT_DIR is used. I think of:
* a subdirectory in the repository directory
e.g. .git/work_dir which is supposed to be a symlink (or a textfile
containing the path for windows compatibility?)
or
* a configuration variable
Considerations:
Without running setup_git_directory_gently is_bare_repository and
is_inside_git_dir may return wrong values. Except for cmd_init_db I
found no place calling on of the functions without calling
setup_git_directory_gently before.
To do:
git init should probably set bare = false when GIT_WORK_DIR is
exported. And if the idea about configurable working directories gets
implemented it could also set this option accordingly.
---
cache.h | 2 +
environment.c | 2 +
git.c | 12 +++++++++-
setup.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
4 files changed, 80 insertions(+), 6 deletions(-)
@@ -68,6 +68,16 @@ static int handle_options(const char*** argv, int* argc)(*argc)--;}elseif(!prefixcmp(cmd,"--git-dir=")){setenv(GIT_DIR_ENVIRONMENT,cmd+10,1);+}elseif(!strcmp(cmd,"--work-dir")){+if(*argc<2){+fprintf(stderr,"No directory given for --work-dir.\n");+usage(git_usage_string);+}+setenv(GIT_WORKING_DIR_ENVIRONMENT,(*argv)[1],1);+(*argv)++;+(*argc)--;+}elseif(!prefixcmp(cmd,"--work-dir=")){+setenv(GIT_WORKING_DIR_ENVIRONMENT,cmd+11,1);}elseif(!strcmp(cmd,"--bare")){staticchargit_dir[PATH_MAX+1];setenv(GIT_DIR_ENVIRONMENT,getcwd(git_dir,sizeof(git_dir)),1);
@@ -192,6 +192,8 @@ int is_inside_git_dir(void)returninside_git_dir;}+inthas_working_directory=-1;+constchar*setup_git_directory_gently(int*nongit_ok){staticcharcwd[PATH_MAX+1];
@@ -205,15 +207,73 @@ const char *setup_git_directory_gently(int *nongit_ok)*/gitdirenv=getenv(GIT_DIR_ENVIRONMENT);if(gitdirenv){+structstatst,st_work,st_git;+constchar*gitwd;+char*prefix;+charc;+intlen;+if(PATH_MAX-40<strlen(gitdirenv))die("'$%s' too big",GIT_DIR_ENVIRONMENT);-if(is_git_directory(gitdirenv))-returnNULL;-if(nongit_ok){-*nongit_ok=1;+if(!is_git_directory(gitdirenv)){+if(nongit_ok){+*nongit_ok=1;+returnNULL;+}+die("Not a git repository: '%s'",gitdirenv);+}++gitwd=getenv(GIT_WORKING_DIR_ENVIRONMENT);+if(!gitwd||stat(gitwd,&st_work))returnNULL;+if(inside_git_dir==-1&&stat(gitdirenv,&st_git))+die("Unable to stat git directory");+if(!getcwd(cwd,sizeof(cwd)-1)||cwd[0]!='/')+die("Unable to read current working directory");+len=strlen(cwd);++prefix=cwd+len;+for(;;){+c=*prefix;+*prefix='\0';+if(stat(cwd,&st))+die("Unable to stat '%s'",cwd);+if(st_work.st_dev==st.st_dev&&+st_work.st_ino==st.st_ino)+break;+if(inside_git_dir==-1&&+st_git.st_dev==st.st_dev&&+st_git.st_ino==st.st_ino)+inside_git_dir=1;+*prefix=c;++if(prefix==cwd+1){+has_working_directory=0;+returnNULL;+}+while(*(--prefix)!='/')+;/* do nothing */+if(prefix==cwd)+prefix++;+}++if(chdir(cwd))+die("Cannot change directory to '%s'",cwd);++if(c){+*prefix=c;+prefix++;+cwd[len]='/';+cwd[len+1]='\0';+}else{+prefix=NULL;}-die("Not a git repository: '%s'",gitdirenv);++has_working_directory=1;+if(inside_git_dir==-1)+inside_git_dir=0;++returnprefix;}if(!getcwd(cwd,sizeof(cwd))||cwd[0]!='/')
I propose the following instead of the last two lines:
if (!gitwd)
return NULL;
if (stat(gitwd, &st_work))
die("Unable to stat git working directory %s",gitwd);
+ if (inside_git_dir == -1 && stat(gitdirenv, &st_git))
+ die("Unable to stat git directory");
+ if (!getcwd(cwd, sizeof(cwd)-1) || cwd[0] != '/')
+ die("Unable to read current working directory");
+ len = strlen(cwd);
+
+ prefix = cwd+len;
+ for (;;) {
+ c = *prefix;
+ *prefix = '\0';
+ if (stat(cwd, &st))
+ die("Unable to stat '%s'", cwd);
+ if (st_work.st_dev == st.st_dev &&
+ st_work.st_ino == st.st_ino)
+ break;
+ if (inside_git_dir == -1 &&
+ st_git.st_dev == st.st_dev &&
+ st_git.st_ino == st.st_ino)
+ inside_git_dir = 1;
+ *prefix = c;
+
+ if (prefix == cwd+1) {
+ has_working_directory = 0;
+ return NULL;
My case seems a bit complicated than usual. The working directory
(/home/pclouds/blog/data) was not a prefix of cwd (/home/pclouds/blog)
so the code failed silently at this line. If I replace
"has_working_directory = 0; return NULL;" with "strcpy(cwd,gitwd);c =
0;break;", it may work but see below
+ }
+ while (*(--prefix) != '/')
+ ; /* do nothing */
+ if (prefix == cwd)
+ prefix++;
+ }
+
+ if (chdir(cwd))
+ die("Cannot change directory to '%s'", cwd);
+
If cwd changed and GIT_DIR is a relative path, git can no longer
access GIT_DIR properly.
--
Duy
My case seems a bit complicated than usual. The working directory
(/home/pclouds/blog/data) was not a prefix of cwd (/home/pclouds/blog)
so the code failed silently at this line. If I replace
"has_working_directory = 0; return NULL;" with "strcpy(cwd,gitwd);c =
0;break;", it may work but see below
If you're outside the specifed working directory the
is_bare_repository will return true, just as if you don't have a
working directory. Do you expect anything else or doesn't this work?
On 3/11/07, Matthias Lederhofer [off-list ref] wrote:
Nguyen Thai Ngoc Duy [off-list ref] wrote:
quoted
My case seems a bit complicated than usual. The working directory
(/home/pclouds/blog/data) was not a prefix of cwd (/home/pclouds/blog)
so the code failed silently at this line. If I replace
"has_working_directory = 0; return NULL;" with "strcpy(cwd,gitwd);c =
0;break;", it may work but see below
If you're outside the specifed working directory the
is_bare_repository will return true, just as if you don't have a
working directory. Do you expect anything else or doesn't this work?
Yes I expected it to move the specified working directory as described
in the previous mail (copied/pasted below). However the patch requires
me to be in workdir somewhere already (which is fine if that is your
expectation). If that's the case, maybe you should tell users
something about GIT_WORK_DIR not applicable.
Nguyen Thai Ngoc Duy [off-list ref] wrote:
quoted
By the way, is it plausible to add --git-workdir option to specify
working directory? With that option, I won't need to _chdir_ to the
working directory, run git commands and _chdir back_.
Yes I expected it to move the specified working directory as described
in the previous mail (copied/pasted below). However the patch requires
me to be in workdir somewhere already (which is fine if that is your
expectation). If that's the case, maybe you should tell users
something about GIT_WORK_DIR not applicable.
Let's say we have GIT_DIR=/tmp/git GIT_WORK_DIR=/tmp/foo and are in
/tmp. You want `git add bar` to chdir to /tmp/foo and add the file
bar from /tmp/foo?
quoted
Nguyen Thai Ngoc Duy [off-list ref] wrote:
quoted
By the way, is it plausible to add --git-workdir option to specify
working directory? With that option, I won't need to _chdir_ to the
working directory, run git commands and _chdir back_.
I thought you meant the chdir to the toplevel directory when you're in
a subdirectory. For this case I'd rather suggest
mygit() {
old=$(pwd)
cd "$MYTOPDIR"
git "$@"
ret=$?
cd "$old"
return $ret
}
On 3/11/07, Matthias Lederhofer [off-list ref] wrote:
Nguyen Thai Ngoc Duy [off-list ref] wrote:
quoted
Yes I expected it to move the specified working directory as described
in the previous mail (copied/pasted below). However the patch requires
me to be in workdir somewhere already (which is fine if that is your
expectation). If that's the case, maybe you should tell users
something about GIT_WORK_DIR not applicable.
Let's say we have GIT_DIR=/tmp/git GIT_WORK_DIR=/tmp/foo and are in
/tmp. You want `git add bar` to chdir to /tmp/foo and add the file
bar from /tmp/foo?
Yes. I wanted it for easy scripting but it's not very intuitive from
command line. I'd take it back.
quoted
quoted
Nguyen Thai Ngoc Duy [off-list ref] wrote:
quoted
By the way, is it plausible to add --git-workdir option to specify
working directory? With that option, I won't need to _chdir_ to the
working directory, run git commands and _chdir back_.
I thought you meant the chdir to the toplevel directory when you're in
a subdirectory. For this case I'd rather suggest
mygit() {
old=$(pwd)
cd "$MYTOPDIR"
git "$@"
ret=$?
cd "$old"
return $ret
}
Um.. git-sh-setup.sh may need special treatment because its
is_bare_directory doesn't call this function.
Here is rev-parse --is-bare-repository to fix this.
I'm not sure if git-sh-setup.sh:is_bare_repository should do other
checks if git-rev-parse --is-bare-repository fails.
---
Documentation/git-rev-parse.txt | 7 +++++++
builtin-rev-parse.c | 5 +++++
git-sh-setup.sh | 6 +-----
git-svn.perl | 2 +-
4 files changed, 14 insertions(+), 6 deletions(-)
@@ -89,6 +89,13 @@ OPTIONS --git-dir:: Show `$GIT_DIR` if defined else show the path to the .git directory.+--is-inside-git-dir::+ When the current working directory is below the repository+ directory print "true", otherwise "false".++--is-bare-repository::+ When the repository is bare print "true", otherwise "false".+ --short, --short=number:: Instead of outputting the full SHA1 values of object names try to abbreviate them to a shorter unique name. When no length is specified
This environment variable can be used with GIT_DIR to
specify the toplevel working directory. When GIT_DIR is not
set this variable is ignored. As for GIT_DIR there is also
the option git --work-dir which overrides the environment
variable.
Signed-off-by: Matthias Lederhofer <redacted>
---
New patch, this should go with the 'rev-parse --is-bare-repository
option' patch.
Documentation added, is_bare_repository check fixed, relative GIT_DIR
fix. Becaus GIT_DIR is expanded to a full path setup_git_env should
be called after setup_git_directory_gently. I searched for the
callers of setup_git_directory_gently and think this is fulfilled.
Nguyen Thai Ngoc Duy [off-list ref] wrote:
I propose the following instead of the last two lines:
if (!gitwd)
return NULL;
if (stat(gitwd, &st_work))
die("Unable to stat git working directory %s",gitwd);
It's in this new patch.
If cwd changed and GIT_DIR is a relative path, git can no longer
access GIT_DIR properly.
@@ -81,6 +82,13 @@ OPTIONS Set the path to the repository. This can also be controlled by setting the GIT_DIR environment variable.+--work-dir=<path>::+ Set the path to the toplevel working directory. The value will+ be used only in combination with $GIT_DIR or '--git-dir'.+ Without this option git will assume that the current directory+ is also the toplevel directory. This can also be controlled by+ setting the GIT_WORK_DIR environment variable.+ --bare:: Same as --git-dir=`pwd`.
@@ -325,6 +333,12 @@ git so take care if using Cogito etc. specifies a path to use instead of the default `.git` for the base of the repository.+'GIT_WORK_DIR'::+ Set the path to the toplevel working directory. The value will+ be used only in combination with $GIT_DIR or '--git-dir'.+ Without this environment variable git will assume that the+ current directory is also the toplevel directory.+ git Commits ~~~~~~~~~~~ 'GIT_AUTHOR_NAME'::
@@ -59,8 +59,15 @@ static void setup_git_env(void)intis_bare_repository(void){constchar*dir,*s;-if(0<=is_bare_repository_cfg)-returnis_bare_repository_cfg;+/* definitely bare */+if(is_bare_repository_cfg==1)+return1;+/* GIT_WORK_DIR is set, bare if cwd is outside */+if(has_working_directory>=0)+return!has_working_directory;+/* configuration says it is not bare */+if(is_bare_repository_cfg==0)+return0;dir=get_git_dir();if(!strcmp(dir,DEFAULT_GIT_DIR_ENVIRONMENT))
@@ -68,6 +68,16 @@ static int handle_options(const char*** argv, int* argc)(*argc)--;}elseif(!prefixcmp(cmd,"--git-dir=")){setenv(GIT_DIR_ENVIRONMENT,cmd+10,1);+}elseif(!strcmp(cmd,"--work-dir")){+if(*argc<2){+fprintf(stderr,"No directory given for --work-dir.\n");+usage(git_usage_string);+}+setenv(GIT_WORKING_DIR_ENVIRONMENT,(*argv)[1],1);+(*argv)++;+(*argc)--;+}elseif(!prefixcmp(cmd,"--work-dir=")){+setenv(GIT_WORKING_DIR_ENVIRONMENT,cmd+11,1);}elseif(!strcmp(cmd,"--bare")){staticchargit_dir[PATH_MAX+1];setenv(GIT_DIR_ENVIRONMENT,getcwd(git_dir,sizeof(git_dir)),1);
@@ -192,28 +192,100 @@ int is_inside_git_dir(void)returninside_git_dir;}+inthas_working_directory=-1;+constchar*setup_git_directory_gently(int*nongit_ok){staticcharcwd[PATH_MAX+1];constchar*gitdirenv;intlen,offset;-/*-*IfGIT_DIRissetexplicitly,we'renotgoing-*todoanydiscovery,butwestilldorepository-*validation.-*/gitdirenv=getenv(GIT_DIR_ENVIRONMENT);if(gitdirenv){+structstatst,st_work,st_git;+constchar*gitwd;+char*prefix;+charc;+intlen;+if(PATH_MAX-40<strlen(gitdirenv))die("'$%s' too big",GIT_DIR_ENVIRONMENT);-if(is_git_directory(gitdirenv))-returnNULL;-if(nongit_ok){-*nongit_ok=1;+if(!is_git_directory(gitdirenv)){+if(nongit_ok){+*nongit_ok=1;+returnNULL;+}+die("Not a git repository: '%s'",gitdirenv);+}++/* check for working directory */+gitwd=getenv(GIT_WORKING_DIR_ENVIRONMENT);+if(!gitwd)returnNULL;+if(stat(gitwd,&st_work))+die("Unable to stat git working directory '%s'",gitwd);+if(inside_git_dir==-1&&stat(gitdirenv,&st_git))+die("Unable to stat git directory");+if(!getcwd(cwd,sizeof(cwd)-1)||cwd[0]!='/')+die("Unable to read current working directory");+len=strlen(cwd);++prefix=cwd+len;+for(;;){+c=*prefix;+*prefix='\0';+if(stat(cwd,&st))+die("Unable to stat '%s'",cwd);+if(st_work.st_dev==st.st_dev&&+st_work.st_ino==st.st_ino)+break;+if(inside_git_dir==-1&&+st_git.st_dev==st.st_dev&&+st_git.st_ino==st.st_ino)+inside_git_dir=1;+*prefix=c;++if(prefix==cwd+1){+has_working_directory=0;+returnNULL;+}+while(*(--prefix)!='/')+;/* do nothing */+if(prefix==cwd)+prefix++;+}++/*+*ifGIT_DIRisnoabsolutepathitwontworkanymoreafter+*changingthedirectory,thereforeexpandittoanabsolute+*path+*/+if(gitdirenv[0]!='/'){+charbuf[PATH_MAX];+if(chdir(gitdirenv))+die("Cannot change directory to '%s'",+gitdirenv);+if(!getcwd(buf,sizeof(buf))||buf[0]!='/')+die("Unable to read current working directory");+setenv(GIT_DIR_ENVIRONMENT,buf,1);+}+if(chdir(cwd))+die("Cannot change directory to '%s'",cwd);++if(c){+*prefix=c;+prefix++;+cwd[len]='/';+cwd[len+1]='\0';+}else{+prefix=NULL;}-die("Not a git repository: '%s'",gitdirenv);++has_working_directory=1;+if(inside_git_dir==-1)+inside_git_dir=0;++returnprefix;}if(!getcwd(cwd,sizeof(cwd)-1)||cwd[0]!='/')
On 3/11/07, Matthias Lederhofer [off-list ref] wrote:
This environment variable can be used with GIT_DIR to
specify the toplevel working directory. When GIT_DIR is not
set this variable is ignored. As for GIT_DIR there is also
the option git --work-dir which overrides the environment
variable.
Signed-off-by: Matthias Lederhofer <redacted>
$GIT_DIR/workdir will be used as fallback if $GIT_WORK_DIR is not set
Signed-off-by: Matthias Lederhofer <redacted>
---
Documentation/repository-layout.txt | 4 ++
setup.c | 64 ++++++++++++++++++++++++++++++++---
2 files changed, 63 insertions(+), 5 deletions(-)
@@ -179,3 +179,7 @@ shallow:: and maintained by shallow clone mechanism. See `--depth` option to gitlink:git-clone[1] and gitlink:git-fetch[1].+workdir::+ Directory to be used as toplevel working directory when GIT_DIR+ is set. If this is a file the first line will be used as the+ name of the directory. This can be overriden by GIT_WORK_DIR.
@@ -192,6 +192,64 @@ int is_inside_git_dir(void)returninside_git_dir;}+staticintstat_git_work_dir(structstat*st)+{+charworkdir[PATH_MAX],cwd[PATH_MAX];+constchar*gitdir=getenv(GIT_DIR_ENVIRONMENT);+constchar*gitwd=getenv(GIT_WORKING_DIR_ENVIRONMENT);+intoffset;+FILE*fp;++if(gitwd){+if(!stat(gitwd,st))+return1;+die("Unable to stat git working directory '%s'",gitwd);+}++/* setup_git_directory_gently: PATH_MAX - 40 >= strlen(gitdirenv) */+strcpy(workdir,gitdir);+strcat(workdir,"/workdir");++if(stat(workdir,st))+return0;+if(st->st_mode&S_IFDIR)+return1;+if(!(st->st_mode&S_IFREG))+die("GIT_DIR/workdir is neither a file nor a directory");++/* GIT_DIR/workdir is a file */+fp=fopen(workdir,"r");+if(!fp)+die("Unable to open '%s'",workdir);+if(!fgets(workdir,sizeof(workdir),fp))+die("Reading working directory from '%s' failed",workdir);+fclose(fp);+/* remove newline character(s) */+offset=strlen(workdir)-1;+while(offset>=0&&(workdir[offset]=='\r'||+workdir[offset]=='\n'))+--offset;+workdir[offset+1]='\0';++/* relative path: change to gitdir for stat */+if(workdir[0]!='/'){+if(!getcwd(cwd,sizeof(cwd))||cwd[0]!='/')+die("Unable to read current working directory");+if(chdir(gitdir))+die("Cannot change directory to '%s'",gitdir);+}++if(stat(workdir,st))+die("Unable to stat directory from GIT_DIR/workdir");+if(!(st->st_mode&S_IFDIR))+die("GIT_DIR/workdir does not point to a directory");++if(workdir[0]!='/'&&chdir(cwd))+die("Cannot come back to cwd");++return1;+}+inthas_working_directory=-1;constchar*setup_git_directory_gently(int*nongit_ok)
@@ -219,11 +276,8 @@ const char *setup_git_directory_gently(int *nongit_ok)}/* check for working directory */-gitwd=getenv(GIT_WORKING_DIR_ENVIRONMENT);-if(!gitwd)+if(!stat_git_work_dir(&st_work))returnNULL;-if(stat(gitwd,&st_work))-die("Unable to stat git working directory '%s'",gitwd);if(inside_git_dir==-1&&stat(gitdirenv,&st_git))die("Unable to stat git directory");if(!getcwd(cwd,sizeof(cwd)-1)||cwd[0]!='/')
git-init will always put an absolute path in
GIT_DIR/workdir, relative paths are resolved from the
directory git-init was called from.
Signed-off-by: Matthias Lederhofer <redacted>
---
I found this static char path[PATH_MAX] even though path is neither
reused nor returned. If there is any reason to have this as a static
buffer please change this back to 'static char'
---
builtin-init-db.c | 40 ++++++++++++++++++++++++++++++++++++++--
1 files changed, 38 insertions(+), 2 deletions(-)
@@ -252,7 +253,42 @@ static int create_default_files(const char *git_dir, const char *template_path)}git_config_set("core.filemode",filemode?"true":"false");-if(is_bare_repository()){+/* make gitwd an absolute path */+if(gitwd&&gitwd[0]!='/'){+charcwd[PATH_MAX];++if(!getcwd(cwd,sizeof(cwd))||cwd[0]!='/')+die("Unable to read current working directory");+if(chdir(gitwd)){+fprintf(stderr,"warning: chdir to specified relative "+"working directory failed, ignoring\n");+gitwd=NULL;+}+elseif(!getcwd(workdir,sizeof(workdir))||workdir[0]!='/')+die("Unable to read current working directory");+else{+gitwd=workdir;+if(chdir(cwd))+die("Cannot come back to cwd");+}+}++if(gitwd){+FILE*fp=NULL;++path[len]=0;+strcpy(path+len,"workdir");+if(!(fp=fopen(path,"w")))+die("Cannot open GIT_DIR/workdir");+fprintf(fp,"%s\n",gitwd);+fclose(fp);++git_config_set("core.bare","false");+/* allow template config file to override the default */+if(log_all_ref_updates==-1)+git_config_set("core.logallrefupdates","true");+}+elseif(is_bare_repository()){git_config_set("core.bare","true");}else{
On Mon, Mar 12, 2007 at 12:53:50PM +0100, Matthias Lederhofer wrote:
quoted
git-init will always put an absolute path in
GIT_DIR/workdir, relative paths are resolved from the
directory git-init was called from.
Does that mean I can't move my GIT trees around without changing a
config entry? What is that an improvement?
And for the decision to put an absolute path there by default:
Putting $GIT_WORK_DIR as is into $GIT_DIR/workdir is probably not what
the user expects because the content of $GIT_DIR/workdir is
interpreted relative to $GIT_DIR, not the current working directory.
Example:
/tmp$ mkdir repository working_directory
/tmp$ git --git-dir=repository --work-dir=working_directory init
If git init puts 'working_directory' into $GIT_DIR/workdir it would
make the associated working directory $GIT_DIR/working_directory =
/tmp/repository/working_directory and not /tmp/working_directory.
The alternative to use
/tmp$ git --git-dir=repository --work-dir=../working_directory init
seems quite confusing to me.
If you've any other idea to solve this please tell me.
On 3/12/07, Matthias Lederhofer [off-list ref] wrote:
Putting $GIT_WORK_DIR as is into $GIT_DIR/workdir is probably not what
the user expects because the content of $GIT_DIR/workdir is
interpreted relative to $GIT_DIR, not the current working directory.
Example:
/tmp$ mkdir repository working_directory
/tmp$ git --git-dir=repository --work-dir=working_directory init
If git init puts 'working_directory' into $GIT_DIR/workdir it would
make the associated working directory $GIT_DIR/working_directory =
/tmp/repository/working_directory and not /tmp/working_directory.
The alternative to use
/tmp$ git --git-dir=repository --work-dir=../working_directory init
seems quite confusing to me.
If you've any other idea to solve this please tell me.
Let users create $GIT_DIR/workdir themselves. Your way may be less
confusing to you but might be more confusing to me because I _might_
expect a relative workdir setting (for example I move the repository
and the working directory together to another place).
--
Duy
Let users create $GIT_DIR/workdir themselves. Your way may be less
confusing to you but might be more confusing to me because I _might_
expect a relative workdir setting (for example I move the repository
and the working directory together to another place).
Well, without this patch you havo to do one of these:
/tmp$ mkdir repository working_directory
/tmp$ git --git-dir=repository init
/tmp$ git --git-dir=repository config core.bare false
/tmp$ echo ../working_directory > repository/workdir
or
/tmp$ mkdir repository working_directory
/tmp/repository$ cd repository
/tmp$ git init
/tmp/repository$ mv .git/* .
/tmp/repository$ rmdir .git
/tmp$ echo ../working_directory > repository/workdir
Where the second example is probably better because git init creates a
bare repository in the first case which might have more settings
different from a 'normal' repository (it actually sets also
core.logallrefupdates = true which probably should be added to the
first example).
With this patch you'd have to do
/tmp$ mkdir repository working_directory
/tmp$ git --git-dir=repository --work-dir=working_directory init
/tmp$ echo ../working_directory > repository/workdir
in case you really want a relative path.
Because the first two ways are so long I think git init should have
some way to handle this case.
I don't want to put $GIT_WORK_DIR 'as is' to $GIT_DIR/workdir because
$GIT_WORK_DIR is normally interpreted as relative path to the current
working directory and not relative to $GIT_DIR.
Perhaps we could add another flag to git init which will be used 'as is'
for $GIT_DIR/workdir:
git --git-dir=repository init --work-dir=../working_directory
Other things I can think of:
Add a --not-bare flag to git init:
$ git --git-dir=repository init --not-bare
$ echo ../working_directory > repository/workdir
Tell the user what to do in case the path should be relative:
$ git --git-dir=repository --work-dir=working_directory init
You specified a relative working directory and git has
automatically expanded this to /tmp/working_directory. If you
prefer a relative path you can do:
echo relative_path > repository/workdir
core.workdir is used as default value for $GIT_WORK_DIR
Signed-off-by: Matthias Lederhofer <redacted>
---
This one replaces the 'use $GIT_DIR/workdir as working directory with
$GIT_DIR' patch and uses core.workdir instead. This patch gets
core.workdir only for setup.c from the configuration file. Perhaps
this should be handled in git_default_config like most other core.*
variables.
I just noticed that dying if the specified workdir is invalid can
cause trouble too:
$ export GIT_DIR=/path/to/repository
$ git config core.workdir /non-existent
$ git config core.workdir ../workdir
fatal: Unable to stat git working directory '/non-existent'
Workaround is either to edit the file manually or do:
$ git --work-dir=. config core.workdir ../workdir
---
Documentation/config.txt | 4 +++
setup.c | 53 +++++++++++++++++++++++++++++++++++++++++----
2 files changed, 52 insertions(+), 5 deletions(-)
@@ -162,6 +162,10 @@ repository that ends in "/.git" is assumed to be not bare (bare = false), while all other repositories are assumed to be bare (bare = true).+core.workdir::+ Directory to be used as toplevel working directory when GIT_DIR+ is set. This can be overriden by GIT_WORK_DIR.+ core.logAllRefUpdates:: Updates to a ref <ref> is logged to the file "$GIT_DIR/logs/<ref>", by appending the new and old
@@ -192,6 +192,53 @@ int is_inside_git_dir(void)returninside_git_dir;}+staticchar**git_work_dir;++staticintgit_workdir_config(constchar*var,constchar*value)+{+if(!strcmp(var,"core.workdir")){+strlcpy(value,*git_work_dir,PATH_MAX);+}+return0;+}++staticintstat_git_work_dir(structstat*st)+{+charworkdir[PATH_MAX],cwd[PATH_MAX];+constchar*gitdir=getenv(GIT_DIR_ENVIRONMENT);+constchar*gitwd=getenv(GIT_WORKING_DIR_ENVIRONMENT);++if(gitwd){+if(!stat(gitwd,st))+return1;+die("Unable to stat git working directory '%s'",gitwd);+}++/* get workdir from config */+workdir[0]='\0';+git_work_dir=workdir;+git_config(git_workdir_config);+git_workdir_config=NULL;+if(!workdir[0])+return0;++/* relative path: change to gitdir for stat */+if(workdir[0]!='/'){+if(!getcwd(cwd,sizeof(cwd))||cwd[0]!='/')+die("Unable to read current working directory");+if(chdir(gitdir))+die("Cannot change directory to '%s'",gitdir);+}++if(stat(workdir,st))+die("Unable to stat git working directory '%s'",workdir);++if(workdir[0]!='/'&&chdir(cwd))+die("Cannot come back to cwd");++return1;+}+inthas_working_directory=-1;constchar*setup_git_directory_gently(int*nongit_ok)
@@ -219,11 +265,8 @@ const char *setup_git_directory_gently(int *nongit_ok)}/* check for working directory */-gitwd=getenv(GIT_WORKING_DIR_ENVIRONMENT);-if(!gitwd)+if(!stat_git_work_dir(&st_work))returnNULL;-if(stat(gitwd,&st_work))-die("Unable to stat git working directory '%s'",gitwd);if(inside_git_dir==-1&&stat(gitdirenv,&st_git))die("Unable to stat git directory");if(!getcwd(cwd,sizeof(cwd)-1)||cwd[0]!='/')
core.workdir is used as default value for $GIT_WORK_DIR
Signed-off-by: Matthias Lederhofer <redacted>
---
Sorry, the last one was totally broken. Testing without recompiling
isn't good..
---
Documentation/config.txt | 4 +++
setup.c | 53 +++++++++++++++++++++++++++++++++++++++++----
2 files changed, 52 insertions(+), 5 deletions(-)
@@ -162,6 +162,10 @@ repository that ends in "/.git" is assumed to be not bare (bare = false), while all other repositories are assumed to be bare (bare = true).+core.workdir::+ Directory to be used as toplevel working directory when GIT_DIR+ is set. This can be overriden by GIT_WORK_DIR.+ core.logAllRefUpdates:: Updates to a ref <ref> is logged to the file "$GIT_DIR/logs/<ref>", by appending the new and old
@@ -192,6 +192,53 @@ int is_inside_git_dir(void)returninside_git_dir;}+staticchar*git_work_dir;++staticintgit_workdir_config(constchar*var,constchar*value)+{+if(!strcmp(var,"core.workdir")){+strlcpy(git_work_dir,value,PATH_MAX);+}+return0;+}++staticintstat_git_work_dir(structstat*st)+{+charworkdir[PATH_MAX],cwd[PATH_MAX];+constchar*gitdir=getenv(GIT_DIR_ENVIRONMENT);+constchar*gitwd=getenv(GIT_WORKING_DIR_ENVIRONMENT);++if(gitwd){+if(!stat(gitwd,st))+return1;+die("Unable to stat git working directory '%s'",gitwd);+}++/* get workdir from config */+workdir[0]='\0';+git_work_dir=workdir;+git_config(git_workdir_config);+git_work_dir=NULL;+if(!workdir[0])+return0;++/* relative path: change to gitdir for stat */+if(workdir[0]!='/'){+if(!getcwd(cwd,sizeof(cwd))||cwd[0]!='/')+die("Unable to read current working directory");+if(chdir(gitdir))+die("Cannot change directory to '%s'",gitdir);+}++if(stat(workdir,st))+die("Unable to stat git working directory '%s'",workdir);++if(workdir[0]!='/'&&chdir(cwd))+die("Cannot come back to cwd");++return1;+}+inthas_working_directory=-1;constchar*setup_git_directory_gently(int*nongit_ok)
@@ -219,11 +265,8 @@ const char *setup_git_directory_gently(int *nongit_ok)}/* check for working directory */-gitwd=getenv(GIT_WORKING_DIR_ENVIRONMENT);-if(!gitwd)+if(!stat_git_work_dir(&st_work))returnNULL;-if(stat(gitwd,&st_work))-die("Unable to stat git working directory '%s'",gitwd);if(inside_git_dir==-1&&stat(gitdirenv,&st_git))die("Unable to stat git directory");if(!getcwd(cwd,sizeof(cwd)-1)||cwd[0]!='/')
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:42:59
Matthias Lederhofer [off-list ref] wrote:
core.workdir is used as default value for $GIT_WORK_DIR
...
--
gitgui.0.6.3.g4bccd
Really? gitgui generates emails now? ;-)
Matthias, your git binaries were built with an older (pre 1.5.0)
git-describe in the path. This caused the version number to be
incorrectly determined, due to an old bug in git-describe.
Recompiling with your "gitgui.0.6.3" git-describe should get
the correct version number, as that is most definately after the
git-describe bug fix.
--
Shawn.