2005-10-12 01:47:34 +00:00
|
|
|
/*
|
|
|
|
* We put all the git config variables in this same object
|
|
|
|
* file, so that programs can link against the config parser
|
|
|
|
* without having to link against all the rest of git.
|
|
|
|
*
|
|
|
|
* In particular, no need to bring in libz etc unless needed,
|
|
|
|
* even if you might want to know where the git directory etc
|
|
|
|
* are.
|
|
|
|
*/
|
|
|
|
#include "cache.h"
|
2018-08-15 17:54:07 +00:00
|
|
|
#include "branch.h"
|
2017-06-22 18:43:33 +00:00
|
|
|
#include "repository.h"
|
2017-06-14 18:07:36 +00:00
|
|
|
#include "config.h"
|
ref namespaces: infrastructure
Add support for dividing the refs of a single repository into multiple
namespaces, each of which can have its own branches, tags, and HEAD.
Git can expose each namespace as an independent repository to pull from
and push to, while sharing the object store, and exposing all the refs
to operations such as git-gc.
Storing multiple repositories as namespaces of a single repository
avoids storing duplicate copies of the same objects, such as when
storing multiple branches of the same source. The alternates mechanism
provides similar support for avoiding duplicates, but alternates do not
prevent duplication between new objects added to the repositories
without ongoing maintenance, while namespaces do.
To specify a namespace, set the GIT_NAMESPACE environment variable to
the namespace. For each ref namespace, git stores the corresponding
refs in a directory under refs/namespaces/. For example,
GIT_NAMESPACE=foo will store refs under refs/namespaces/foo/. You can
also specify namespaces via the --namespace option to git.
Note that namespaces which include a / will expand to a hierarchy of
namespaces; for example, GIT_NAMESPACE=foo/bar will store refs under
refs/namespaces/foo/refs/namespaces/bar/. This makes paths in
GIT_NAMESPACE behave hierarchically, so that cloning with
GIT_NAMESPACE=foo/bar produces the same result as cloning with
GIT_NAMESPACE=foo and cloning from that repo with GIT_NAMESPACE=bar. It
also avoids ambiguity with strange namespace paths such as
foo/refs/heads/, which could otherwise generate directory/file conflicts
within the refs directory.
Add the infrastructure for ref namespaces: handle the GIT_NAMESPACE
environment variable and --namespace option, and support iterating over
refs in a namespace.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-07-05 17:54:44 +00:00
|
|
|
#include "refs.h"
|
2011-10-09 17:33:34 +00:00
|
|
|
#include "fmt-merge-msg.h"
|
2013-12-05 13:02:45 +00:00
|
|
|
#include "commit.h"
|
2018-03-03 11:35:55 +00:00
|
|
|
#include "argv-array.h"
|
2018-03-23 17:20:55 +00:00
|
|
|
#include "object-store.h"
|
set_work_tree: use chdir_notify
When we change to the top of the working tree, we manually
re-adjust $GIT_DIR and call set_git_dir() again, in order to
update any relative git-dir we'd compute earlier.
Instead of the work-tree code having to know to call the
git-dir code, let's use the new chdir_notify interface.
There are two spots that need updating, with a few
subtleties in each:
1. the set_git_dir() code needs to chdir_notify_register()
so it can be told when to update its path.
Technically we could push this down into repo_set_gitdir(),
so that even repository structs besides the_repository
could benefit from this. But that opens up a lot of
complications:
- we'd still need to touch set_git_dir(), because it
does some other setup (like setting $GIT_DIR in the
environment)
- submodules using other repository structs get
cleaned up, which means we'd need to remove them
from the chdir_notify list
- it's unlikely to fix any bugs, since we shouldn't
generally chdir() in the middle of working on a
submodule
2. setup_work_tree now needs to call chdir_notify(), and
can lose its manual set_git_dir() call.
Note that at first glance it looks like this undoes the
absolute-to-relative optimization added by 044bbbcb63
(Make git_dir a path relative to work_tree in
setup_work_tree(), 2008-06-19). But for the most part
that optimization was just _undoing_ the
relative-to-absolute conversion which the function was
doing earlier (and which is now gone).
It is true that if you already have an absolute git_dir
that the setup_work_tree() function will no longer make
it relative as a side effect. But:
- we generally do have relative git-dir's due to the
way the discovery code works
- if we really care about making git-dir's relative
when possible, then we should be relativizing them
earlier (e.g., when we see an absolute $GIT_DIR we
could turn it relative, whether we are going to
chdir into a worktree or not). That would cover all
cases, including ones that 044bbbcb63 did not.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-03-30 18:35:08 +00:00
|
|
|
#include "chdir-notify.h"
|
2005-10-12 01:47:34 +00:00
|
|
|
|
|
|
|
int trust_executable_bit = 1;
|
2008-07-28 06:31:28 +00:00
|
|
|
int trust_ctime = 1;
|
2013-01-22 07:49:22 +00:00
|
|
|
int check_stat = 1;
|
2007-03-02 21:11:30 +00:00
|
|
|
int has_symlinks = 1;
|
2016-10-01 00:19:37 +00:00
|
|
|
int minimum_abbrev = 4, default_abbrev = -1;
|
2008-03-21 23:52:46 +00:00
|
|
|
int ignore_case;
|
2006-08-15 17:23:48 +00:00
|
|
|
int assume_unchanged;
|
|
|
|
int prefer_symlink_refs;
|
2007-01-07 10:00:28 +00:00
|
|
|
int is_bare_repository_cfg = -1; /* unspecified */
|
2006-03-24 07:42:40 +00:00
|
|
|
int warn_ambiguous_refs = 1;
|
cat-file: disable object/refname ambiguity check for batch mode
A common use of "cat-file --batch-check" is to feed a list
of objects from "rev-list --objects" or a similar command.
In this instance, all of our input objects are 40-byte sha1
ids. However, cat-file has always allowed arbitrary revision
specifiers, and feeds the result to get_sha1().
Fortunately, get_sha1() recognizes a 40-byte sha1 before
doing any hard work trying to look up refs, meaning this
scenario should end up spending very little time converting
the input into an object sha1. However, since 798c35f
(get_sha1: warn about full or short object names that look
like refs, 2013-05-29), when we encounter this case, we
spend the extra effort to do a refname lookup anyway, just
to print a warning. This is further exacerbated by ca91993
(get_packed_ref_cache: reload packed-refs file when it
changes, 2013-06-20), which makes individual ref lookup more
expensive by requiring a stat() of the packed-refs file for
each missing ref.
With no patches, this is the time it takes to run:
$ git rev-list --objects --all >objects
$ time git cat-file --batch-check='%(objectname)' <objects
on the linux.git repository:
real 1m13.494s
user 0m25.924s
sys 0m47.532s
If we revert ca91993, the packed-refs up-to-date check, it
gets a little better:
real 0m54.697s
user 0m21.692s
sys 0m32.916s
but we are still spending quite a bit of time on ref lookup
(and we would not want to revert that patch, anyway, which
has correctness issues). If we revert 798c35f, disabling
the warning entirely, we get a much more reasonable time:
real 0m7.452s
user 0m6.836s
sys 0m0.608s
This patch does the moral equivalent of this final case (and
gets similar speedups). We introduce a global flag that
callers of get_sha1() can use to avoid paying the price for
the warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-12 06:20:05 +00:00
|
|
|
int warn_on_object_refname_ambiguity = 1;
|
2015-03-20 18:43:06 +00:00
|
|
|
int ref_paranoia = -1;
|
2015-06-23 10:54:11 +00:00
|
|
|
int repository_format_precious_objects;
|
2018-10-21 14:02:28 +00:00
|
|
|
int repository_format_worktree_config;
|
2007-03-12 19:33:18 +00:00
|
|
|
const char *git_commit_encoding;
|
2007-03-07 01:44:17 +00:00
|
|
|
const char *git_log_output_encoding;
|
2006-08-15 17:23:48 +00:00
|
|
|
const char *apply_default_whitespace;
|
2009-08-04 11:16:49 +00:00
|
|
|
const char *apply_default_ignorewhitespace;
|
2011-10-06 18:22:24 +00:00
|
|
|
const char *git_attributes_file;
|
2016-05-04 22:58:12 +00:00
|
|
|
const char *git_hooks_path;
|
Custom compression levels for objects and packs
Add config variables pack.compression and core.loosecompression ,
and switch --compression=level to pack-objects.
Loose objects will be compressed using core.loosecompression if set,
else core.compression if set, else Z_BEST_SPEED.
Packed objects will be compressed using --compression=level if seen,
else pack.compression if set, else core.compression if set,
else Z_DEFAULT_COMPRESSION. This is the "pack compression level".
Loose objects added to a pack undeltified will be recompressed
to the pack compression level if it is unequal to the current
loose compression level by the preceding rules, or if the loose
object was written while core.legacyheaders = true. Newly
deltified loose objects are always compressed to the current
pack compression level.
Previously packed objects added to a pack are recompressed
to the current pack compression level exactly when their
deltification status changes, since the previous pack data
cannot be reused.
In either case, the --no-reuse-object switch from the first
patch below will always force recompression to the current pack
compression level, instead of assuming the pack compression level
hasn't changed and pack data can be reused when possible.
This applies on top of the following patches from Nicolas Pitre:
[PATCH] allow for undeltified objects not to be reused
[PATCH] make "repack -f" imply "pack-objects --no-reuse-object"
Signed-off-by: Dana L. How <danahow@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-05-09 20:56:50 +00:00
|
|
|
int zlib_compression_level = Z_BEST_SPEED;
|
|
|
|
int core_compression_level;
|
2016-11-16 01:42:40 +00:00
|
|
|
int pack_compression_level = Z_DEFAULT_COMPRESSION;
|
2008-06-18 22:18:44 +00:00
|
|
|
int fsync_object_files;
|
2006-12-24 05:46:13 +00:00
|
|
|
size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
|
|
|
|
size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
|
2014-05-04 17:13:57 +00:00
|
|
|
size_t delta_base_cache_limit = 96 * 1024 * 1024;
|
2011-04-05 17:44:11 +00:00
|
|
|
unsigned long big_file_threshold = 512 * 1024 * 1024;
|
2006-07-29 22:27:43 +00:00
|
|
|
int pager_use_color = 1;
|
2008-02-16 05:01:41 +00:00
|
|
|
const char *editor_program;
|
2010-08-30 13:38:38 +00:00
|
|
|
const char *askpass_program;
|
2008-02-16 05:01:59 +00:00
|
|
|
const char *excludes_file;
|
2010-05-19 20:43:10 +00:00
|
|
|
enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
|
2018-07-18 20:45:20 +00:00
|
|
|
int read_replace_refs = 1;
|
2015-06-11 21:34:59 +00:00
|
|
|
char *git_replace_ref_base;
|
2011-05-09 19:52:12 +00:00
|
|
|
enum eol core_eol = EOL_UNSET;
|
2018-01-13 22:49:31 +00:00
|
|
|
int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
|
2018-04-15 18:16:10 +00:00
|
|
|
char *check_roundtrip_encoding = "SHIFT-JIS";
|
2007-12-06 08:14:14 +00:00
|
|
|
unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
|
2008-02-19 16:24:37 +00:00
|
|
|
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
|
2008-05-10 22:36:29 +00:00
|
|
|
enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
|
push: Provide situational hints for non-fast-forward errors
Pushing a non-fast-forward update to a remote repository will result in
an error, but the hint text doesn't provide the correct resolution in
every case. Give better resolution advice in three push scenarios:
1) If you push your current branch and it triggers a non-fast-forward
error, you should merge remote changes with 'git pull' before pushing
again.
2) If you push to a shared repository others push to, and your local
tracking branches are not kept up to date, the 'matching refs' default
will generate non-fast-forward errors on outdated branches. If this is
your workflow, the 'matching refs' default is not for you. Consider
setting the 'push.default' configuration variable to 'current' or
'upstream' to ensure only your current branch is pushed.
3) If you explicitly specify a ref that is not your current branch or
push matching branches with ':', you will generate a non-fast-forward
error if any pushed branch tip is out of date. You should checkout the
offending branch and merge remote changes before pushing again.
Teach transport.c to recognize these scenarios and configure push.c
to hint for them. If 'git push's default behavior changes or we
discover more scenarios, extension is easy. Standardize on the
advice API and add three new advice variables, 'pushNonFFCurrent',
'pushNonFFDefault', and 'pushNonFFMatching'. Setting any of these
to 'false' will disable their affiliated advice. Setting
'pushNonFastForward' to false will disable all three, thus preserving the
config option for users who already set it, but guaranteeing new
users won't disable push advice accidentally.
Based-on-patch-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Christopher Tiwald <christiwald@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-03-20 04:31:33 +00:00
|
|
|
enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
|
2009-04-27 22:32:25 +00:00
|
|
|
#ifndef OBJECT_CREATION_MODE
|
|
|
|
#define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS
|
2009-04-25 09:57:14 +00:00
|
|
|
#endif
|
2009-04-27 22:32:25 +00:00
|
|
|
enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
|
2009-10-09 10:21:57 +00:00
|
|
|
char *notes_ref_name;
|
2009-07-23 15:33:49 +00:00
|
|
|
int grafts_replace_parents = 1;
|
2009-08-20 13:47:08 +00:00
|
|
|
int core_apply_sparse_checkout;
|
2019-11-21 22:04:40 +00:00
|
|
|
int core_sparse_checkout_cone;
|
2011-10-07 06:12:09 +00:00
|
|
|
int merge_log_config = -1;
|
git on Mac OS and precomposed unicode
Mac OS X mangles file names containing unicode on file systems HFS+,
VFAT or SAMBA. When a file using unicode code points outside ASCII
is created on a HFS+ drive, the file name is converted into
decomposed unicode and written to disk. No conversion is done if
the file name is already decomposed unicode.
Calling open("\xc3\x84", ...) with a precomposed "Ä" yields the same
result as open("\x41\xcc\x88",...) with a decomposed "Ä".
As a consequence, readdir() returns the file names in decomposed
unicode, even if the user expects precomposed unicode. Unlike on
HFS+, Mac OS X stores files on a VFAT drive (e.g. an USB drive) in
precomposed unicode, but readdir() still returns file names in
decomposed unicode. When a git repository is stored on a network
share using SAMBA, file names are send over the wire and written to
disk on the remote system in precomposed unicode, but Mac OS X
readdir() returns decomposed unicode to be compatible with its
behaviour on HFS+ and VFAT.
The unicode decomposition causes many problems:
- The names "git add" and other commands get from the end user may
often be precomposed form (the decomposed form is not easily input
from the keyboard), but when the commands read from the filesystem
to see what it is going to update the index with already is on the
filesystem, readdir() will give decomposed form, which is different.
- Similarly "git log", "git mv" and all other commands that need to
compare pathnames found on the command line (often but not always
precomposed form; a command line input resulting from globbing may
be in decomposed) with pathnames found in the tree objects (should
be precomposed form to be compatible with other systems and for
consistency in general).
- The same for names stored in the index, which should be
precomposed, that may need to be compared with the names read from
readdir().
NFS mounted from Linux is fully transparent and does not suffer from
the above.
As Mac OS X treats precomposed and decomposed file names as equal,
we can
- wrap readdir() on Mac OS X to return the precomposed form, and
- normalize decomposed form given from the command line also to the
precomposed form,
to ensure that all pathnames used in Git are always in the
precomposed form. This behaviour can be requested by setting
"core.precomposedunicode" configuration variable to true.
The code in compat/precomposed_utf8.c implements basically 4 new
functions: precomposed_utf8_opendir(), precomposed_utf8_readdir(),
precomposed_utf8_closedir() and precompose_argv(). The first three
are to wrap opendir(3), readdir(3), and closedir(3) functions.
The argv[] conversion allows to use the TAB filename completion done
by the shell on command line. It tolerates other tools which use
readdir() to feed decomposed file names into git.
When creating a new git repository with "git init" or "git clone",
"core.precomposedunicode" will be set "false".
The user needs to activate this feature manually. She typically
sets core.precomposedunicode to "true" on HFS and VFAT, or file
systems mounted via SAMBA.
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-07-08 13:50:25 +00:00
|
|
|
int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
|
2011-10-28 21:48:40 +00:00
|
|
|
unsigned long pack_size_limit_cfg;
|
2017-01-27 10:09:47 +00:00
|
|
|
enum log_refs_config log_all_ref_updates = LOG_REFS_UNSET;
|
2005-10-12 01:47:34 +00:00
|
|
|
|
2014-12-15 23:15:20 +00:00
|
|
|
#ifndef PROTECT_HFS_DEFAULT
|
|
|
|
#define PROTECT_HFS_DEFAULT 0
|
|
|
|
#endif
|
|
|
|
int protect_hfs = PROTECT_HFS_DEFAULT;
|
|
|
|
|
2014-12-16 22:46:59 +00:00
|
|
|
#ifndef PROTECT_NTFS_DEFAULT
|
protect_ntfs: turn on NTFS protection by default
Back in the DOS days, in the FAT file system, file names always
consisted of a base name of length 8 plus a file extension of length 3.
Shorter file names were simply padded with spaces to the full 8.3
format.
Later, the FAT file system was taught to support _also_ longer names,
with an 8.3 "short name" as primary file name. While at it, the same
facility allowed formerly illegal file names, such as `.git` (empty base
names were not allowed), which would have the "short name" `git~1`
associated with it.
For backwards-compatibility, NTFS supports alternative 8.3 short
filenames, too, even if starting with Windows Vista, they are only
generated on the system drive by default.
We addressed the problem that the `.git/` directory can _also_ be
accessed via `git~1/` (when short names are enabled) in 2b4c6efc821
(read-cache: optionally disallow NTFS .git variants, 2014-12-16), i.e.
since Git v1.9.5, by introducing the config setting `core.protectNTFS`
and enabling it by default on Windows.
In the meantime, Windows 10 introduced the "Windows Subsystem for Linux"
(short: WSL), i.e. a way to run Linux applications/distributions in a
thinly-isolated subsystem on Windows (giving rise to many a "2016 is the
Year of Linux on the Desktop" jokes). WSL is getting increasingly
popular, also due to the painless way Linux application can operate
directly ("natively") on files on Windows' file system: the Windows
drives are mounted automatically (e.g. `C:` as `/mnt/c/`).
Taken together, this means that we now have to enable the safe-guards of
Git v1.9.5 also in WSL: it is possible to access a `.git` directory
inside `/mnt/c/` via the 8.3 name `git~1` (unless short name generation
was disabled manually). Since regular Linux distributions run in WSL,
this means we have to enable `core.protectNTFS` at least on Linux, too.
To enable Services for Macintosh in Windows NT to store so-called
resource forks, NTFS introduced "Alternate Data Streams". Essentially,
these constitute additional metadata that are connected to (and copied
with) their associated files, and they are accessed via pseudo file
names of the form `filename:<stream-name>:<stream-type>`.
In a recent patch, we extended `core.protectNTFS` to also protect
against accesses via NTFS Alternate Data Streams, e.g. to prevent
contents of the `.git/` directory to be "tracked" via yet another
alternative file name.
While it is not possible (at least by default) to access files via NTFS
Alternate Data Streams from within WSL, the defaults on macOS when
mounting network shares via SMB _do_ allow accessing files and
directories in that way. Therefore, we need to enable `core.protectNTFS`
on macOS by default, too, and really, on any Operating System that can
mount network shares via SMB/CIFS.
A couple of approaches were considered for fixing this:
1. We could perform a dynamic NTFS check similar to the `core.symlinks`
check in `init`/`clone`: instead of trying to create a symbolic link
in the `.git/` directory, we could create a test file and try to
access `.git/config` via 8.3 name and/or Alternate Data Stream.
2. We could simply "flip the switch" on `core.protectNTFS`, to make it
"on by default".
The obvious downside of 1. is that it won't protect worktrees that were
clone with a vulnerable Git version already. We considered patching code
paths that check out files to check whether we're running on an NTFS
system dynamically and persist the result in the repository-local config
setting `core.protectNTFS`, but in the end decided that this solution
would be too fragile, and too involved.
The obvious downside of 2. is that everybody will have to "suffer" the
performance penalty incurred from calling `is_ntfs_dotgit()` on every
path, even in setups where.
After the recent work to accelerate `is_ntfs_dotgit()` in most cases,
it looks as if the time spent on validating ten million random
file names increases only negligibly (less than 20ms, well within the
standard deviation of ~50ms). Therefore the benefits outweigh the cost.
Another downside of this is that paths that might have been acceptable
previously now will be forbidden. Realistically, though, this is an
improvement because public Git hosters already would reject any `git
push` that contains such file names.
Note: There might be a similar problem mounting HFS+ on Linux. However,
this scenario has been considered unlikely and in light of the cost (in
the aforementioned benchmark, `core.protectHFS = true` increased the
time from ~440ms to ~610ms), it was decided _not_ to touch the default
of `core.protectHFS`.
This change addresses CVE-2019-1353.
Reported-by: Nicolas Joly <Nicolas.Joly@microsoft.com>
Helped-by: Garima Singh <garima.singh@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-09-09 19:04:41 +00:00
|
|
|
#define PROTECT_NTFS_DEFAULT 1
|
2014-12-16 22:46:59 +00:00
|
|
|
#endif
|
|
|
|
int protect_ntfs = PROTECT_NTFS_DEFAULT;
|
2017-09-22 16:35:40 +00:00
|
|
|
const char *core_fsmonitor;
|
2014-12-16 22:46:59 +00:00
|
|
|
|
2013-01-16 19:18:48 +00:00
|
|
|
/*
|
|
|
|
* The character that begins a commented line in user-editable file
|
|
|
|
* that is subject to stripspace.
|
|
|
|
*/
|
|
|
|
char comment_line_char = '#';
|
2014-05-17 01:52:23 +00:00
|
|
|
int auto_comment_line_char;
|
2013-01-16 19:18:48 +00:00
|
|
|
|
2008-11-14 00:36:30 +00:00
|
|
|
/* Parallel index stat data preload? */
|
2014-06-02 16:43:00 +00:00
|
|
|
int core_preload_index = 1;
|
2008-11-14 00:36:30 +00:00
|
|
|
|
2016-01-27 06:58:06 +00:00
|
|
|
/*
|
|
|
|
* This is a hack for test programs like test-dump-untracked-cache to
|
|
|
|
* ensure that they do not modify the untracked cache when reading it.
|
|
|
|
* Do not use it otherwise!
|
|
|
|
*/
|
|
|
|
int ignore_untracked_cache_config;
|
|
|
|
|
Clean up work-tree handling
The old version of work-tree support was an unholy mess, barely readable,
and not to the point.
For example, why do you have to provide a worktree, when it is not used?
As in "git status". Now it works.
Another riddle was: if you can have work trees inside the git dir, why
are some programs complaining that they need a work tree?
IOW it is allowed to call
$ git --git-dir=../ --work-tree=. bla
when you really want to. In this case, you are both in the git directory
and in the working tree. So, programs have to actually test for the right
thing, namely if they are inside a working tree, and not if they are
inside a git directory.
Also, GIT_DIR=../.git should behave the same as if no GIT_DIR was
specified, unless there is a repository in the current working directory.
It does now.
The logic to determine if a repository is bare, or has a work tree
(tertium non datur), is this:
--work-tree=bla overrides GIT_WORK_TREE, which overrides core.bare = true,
which overrides core.worktree, which overrides GIT_DIR/.. when GIT_DIR
ends in /.git, which overrides the directory in which .git/ was found.
In related news, a long standing bug was fixed: when in .git/bla/x.git/,
which is a bare repository, git formerly assumed ../.. to be the
appropriate git dir. This problem was reported by Shawn Pearce to have
caused much pain, where a colleague mistakenly ran "git init" in "/" a
long time ago, and bare repositories just would not work.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-08-01 00:30:14 +00:00
|
|
|
/* This is set by setup_git_dir_gently() and/or git_default_config() */
|
|
|
|
char *git_work_tree_cfg;
|
|
|
|
|
2018-02-14 18:59:55 +00:00
|
|
|
static char *git_namespace;
|
ref namespaces: infrastructure
Add support for dividing the refs of a single repository into multiple
namespaces, each of which can have its own branches, tags, and HEAD.
Git can expose each namespace as an independent repository to pull from
and push to, while sharing the object store, and exposing all the refs
to operations such as git-gc.
Storing multiple repositories as namespaces of a single repository
avoids storing duplicate copies of the same objects, such as when
storing multiple branches of the same source. The alternates mechanism
provides similar support for avoiding duplicates, but alternates do not
prevent duplication between new objects added to the repositories
without ongoing maintenance, while namespaces do.
To specify a namespace, set the GIT_NAMESPACE environment variable to
the namespace. For each ref namespace, git stores the corresponding
refs in a directory under refs/namespaces/. For example,
GIT_NAMESPACE=foo will store refs under refs/namespaces/foo/. You can
also specify namespaces via the --namespace option to git.
Note that namespaces which include a / will expand to a hierarchy of
namespaces; for example, GIT_NAMESPACE=foo/bar will store refs under
refs/namespaces/foo/refs/namespaces/bar/. This makes paths in
GIT_NAMESPACE behave hierarchically, so that cloning with
GIT_NAMESPACE=foo/bar produces the same result as cloning with
GIT_NAMESPACE=foo and cloning from that repo with GIT_NAMESPACE=bar. It
also avoids ambiguity with strange namespace paths such as
foo/refs/heads/, which could otherwise generate directory/file conflicts
within the refs directory.
Add the infrastructure for ref namespaces: handle the GIT_NAMESPACE
environment variable and --namespace option, and support iterating over
refs in a namespace.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-07-05 17:54:44 +00:00
|
|
|
|
2019-01-11 22:15:00 +00:00
|
|
|
static char *super_prefix;
|
2016-10-07 18:18:48 +00:00
|
|
|
|
2010-02-24 23:34:14 +00:00
|
|
|
/*
|
2013-03-08 09:29:08 +00:00
|
|
|
* Repository-local GIT_* environment variables; see cache.h for details.
|
2010-02-24 23:34:14 +00:00
|
|
|
*/
|
2013-03-08 09:29:08 +00:00
|
|
|
const char * const local_repo_env[] = {
|
2010-02-24 23:34:14 +00:00
|
|
|
ALTERNATE_DB_ENVIRONMENT,
|
|
|
|
CONFIG_ENVIRONMENT,
|
2010-08-24 06:41:14 +00:00
|
|
|
CONFIG_DATA_ENVIRONMENT,
|
2010-02-24 23:34:14 +00:00
|
|
|
DB_ENVIRONMENT,
|
|
|
|
GIT_DIR_ENVIRONMENT,
|
|
|
|
GIT_WORK_TREE_ENVIRONMENT,
|
setup: suppress implicit "." work-tree for bare repos
If an explicit GIT_DIR is given without a working tree, we
implicitly assume that the current working directory should
be used as the working tree. E.g.,:
GIT_DIR=/some/repo.git git status
would compare against the cwd.
Unfortunately, we fool this rule for sub-invocations of git
by setting GIT_DIR internally ourselves. For example:
git init foo
cd foo/.git
git status ;# fails, as we expect
git config alias.st status
git status ;# does not fail, but should
What happens is that we run setup_git_directory when doing
alias lookup (since we need to see the config), set GIT_DIR
as a result, and then leave GIT_WORK_TREE blank (because we
do not have one). Then when we actually run the status
command, we do setup_git_directory again, which sees our
explicit GIT_DIR and uses the cwd as an implicit worktree.
It's tempting to argue that we should be suppressing that
second invocation of setup_git_directory, as it could use
the values we already found in memory. However, the problem
still exists for sub-processes (e.g., if "git status" were
an external command).
You can see another example with the "--bare" option, which
sets GIT_DIR explicitly. For example:
git init foo
cd foo/.git
git status ;# fails
git --bare status ;# does NOT fail
We need some way of telling sub-processes "even though
GIT_DIR is set, do not use cwd as an implicit working tree".
We could do it by putting a special token into
GIT_WORK_TREE, but the obvious choice (an empty string) has
some portability problems.
Instead, we add a new boolean variable, GIT_IMPLICIT_WORK_TREE,
which suppresses the use of cwd as a working tree when
GIT_DIR is set. We trigger the new variable when we know we
are in a bare setting.
The variable is left intentionally undocumented, as this is
an internal detail (for now, anyway). If somebody comes up
with a good alternate use for it, and once we are confident
we have shaken any bugs out of it, we can consider promoting
it further.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-03-08 09:32:22 +00:00
|
|
|
GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,
|
2010-02-24 23:34:14 +00:00
|
|
|
GRAFT_ENVIRONMENT,
|
|
|
|
INDEX_ENVIRONMENT,
|
|
|
|
NO_REPLACE_OBJECTS_ENVIRONMENT,
|
2015-06-11 21:34:59 +00:00
|
|
|
GIT_REPLACE_REF_BASE_ENVIRONMENT,
|
2013-03-08 09:30:25 +00:00
|
|
|
GIT_PREFIX_ENVIRONMENT,
|
2016-10-07 18:18:48 +00:00
|
|
|
GIT_SUPER_PREFIX_ENVIRONMENT,
|
2013-12-05 13:02:45 +00:00
|
|
|
GIT_SHALLOW_FILE_ENVIRONMENT,
|
$GIT_COMMON_DIR: a new environment variable
This variable is intended to support multiple working directories
attached to a repository. Such a repository may have a main working
directory, created by either "git init" or "git clone" and one or more
linked working directories. These working directories and the main
repository share the same repository directory.
In linked working directories, $GIT_COMMON_DIR must be defined to point
to the real repository directory and $GIT_DIR points to an unused
subdirectory inside $GIT_COMMON_DIR. File locations inside the
repository are reorganized from the linked worktree view point:
- worktree-specific such as HEAD, logs/HEAD, index, other top-level
refs and unrecognized files are from $GIT_DIR.
- the rest like objects, refs, info, hooks, packed-refs, shallow...
are from $GIT_COMMON_DIR (except info/sparse-checkout, but that's
a separate patch)
Scripts are supposed to retrieve paths in $GIT_DIR with "git rev-parse
--git-path", which will take care of "$GIT_DIR vs $GIT_COMMON_DIR"
business.
The redirection is done by git_path(), git_pathdup() and
strbuf_git_path(). The selected list of paths goes to $GIT_COMMON_DIR,
not the other way around in case a developer adds a new
worktree-specific file and it's accidentally promoted to be shared
across repositories (this includes unknown files added by third party
commands)
The list of known files that belong to $GIT_DIR are:
ADD_EDIT.patch BISECT_ANCESTORS_OK BISECT_EXPECTED_REV BISECT_LOG
BISECT_NAMES CHERRY_PICK_HEAD COMMIT_MSG FETCH_HEAD HEAD MERGE_HEAD
MERGE_MODE MERGE_RR NOTES_EDITMSG NOTES_MERGE_WORKTREE ORIG_HEAD
REVERT_HEAD SQUASH_MSG TAG_EDITMSG fast_import_crash_* logs/HEAD
next-index-* rebase-apply rebase-merge rsync-refs-* sequencer/*
shallow_*
Path mapping is NOT done for git_path_submodule(). Multi-checkouts are
not supported as submodules.
Helped-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-30 08:24:36 +00:00
|
|
|
GIT_COMMON_DIR_ENVIRONMENT,
|
2010-02-24 23:34:14 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
ref namespaces: infrastructure
Add support for dividing the refs of a single repository into multiple
namespaces, each of which can have its own branches, tags, and HEAD.
Git can expose each namespace as an independent repository to pull from
and push to, while sharing the object store, and exposing all the refs
to operations such as git-gc.
Storing multiple repositories as namespaces of a single repository
avoids storing duplicate copies of the same objects, such as when
storing multiple branches of the same source. The alternates mechanism
provides similar support for avoiding duplicates, but alternates do not
prevent duplication between new objects added to the repositories
without ongoing maintenance, while namespaces do.
To specify a namespace, set the GIT_NAMESPACE environment variable to
the namespace. For each ref namespace, git stores the corresponding
refs in a directory under refs/namespaces/. For example,
GIT_NAMESPACE=foo will store refs under refs/namespaces/foo/. You can
also specify namespaces via the --namespace option to git.
Note that namespaces which include a / will expand to a hierarchy of
namespaces; for example, GIT_NAMESPACE=foo/bar will store refs under
refs/namespaces/foo/refs/namespaces/bar/. This makes paths in
GIT_NAMESPACE behave hierarchically, so that cloning with
GIT_NAMESPACE=foo/bar produces the same result as cloning with
GIT_NAMESPACE=foo and cloning from that repo with GIT_NAMESPACE=bar. It
also avoids ambiguity with strange namespace paths such as
foo/refs/heads/, which could otherwise generate directory/file conflicts
within the refs directory.
Add the infrastructure for ref namespaces: handle the GIT_NAMESPACE
environment variable and --namespace option, and support iterating over
refs in a namespace.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-07-05 17:54:44 +00:00
|
|
|
static char *expand_namespace(const char *raw_namespace)
|
|
|
|
{
|
|
|
|
struct strbuf buf = STRBUF_INIT;
|
|
|
|
struct strbuf **components, **c;
|
|
|
|
|
|
|
|
if (!raw_namespace || !*raw_namespace)
|
|
|
|
return xstrdup("");
|
|
|
|
|
|
|
|
strbuf_addstr(&buf, raw_namespace);
|
|
|
|
components = strbuf_split(&buf, '/');
|
|
|
|
strbuf_reset(&buf);
|
|
|
|
for (c = components; *c; c++)
|
|
|
|
if (strcmp((*c)->buf, "/") != 0)
|
|
|
|
strbuf_addf(&buf, "refs/namespaces/%s", (*c)->buf);
|
|
|
|
strbuf_list_free(components);
|
2011-09-15 21:10:25 +00:00
|
|
|
if (check_refname_format(buf.buf, 0))
|
2018-07-21 07:49:31 +00:00
|
|
|
die(_("bad git namespace path \"%s\""), raw_namespace);
|
ref namespaces: infrastructure
Add support for dividing the refs of a single repository into multiple
namespaces, each of which can have its own branches, tags, and HEAD.
Git can expose each namespace as an independent repository to pull from
and push to, while sharing the object store, and exposing all the refs
to operations such as git-gc.
Storing multiple repositories as namespaces of a single repository
avoids storing duplicate copies of the same objects, such as when
storing multiple branches of the same source. The alternates mechanism
provides similar support for avoiding duplicates, but alternates do not
prevent duplication between new objects added to the repositories
without ongoing maintenance, while namespaces do.
To specify a namespace, set the GIT_NAMESPACE environment variable to
the namespace. For each ref namespace, git stores the corresponding
refs in a directory under refs/namespaces/. For example,
GIT_NAMESPACE=foo will store refs under refs/namespaces/foo/. You can
also specify namespaces via the --namespace option to git.
Note that namespaces which include a / will expand to a hierarchy of
namespaces; for example, GIT_NAMESPACE=foo/bar will store refs under
refs/namespaces/foo/refs/namespaces/bar/. This makes paths in
GIT_NAMESPACE behave hierarchically, so that cloning with
GIT_NAMESPACE=foo/bar produces the same result as cloning with
GIT_NAMESPACE=foo and cloning from that repo with GIT_NAMESPACE=bar. It
also avoids ambiguity with strange namespace paths such as
foo/refs/heads/, which could otherwise generate directory/file conflicts
within the refs directory.
Add the infrastructure for ref namespaces: handle the GIT_NAMESPACE
environment variable and --namespace option, and support iterating over
refs in a namespace.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-07-05 17:54:44 +00:00
|
|
|
strbuf_addch(&buf, '/');
|
|
|
|
return strbuf_detach(&buf, NULL);
|
|
|
|
}
|
|
|
|
|
2018-03-03 11:35:55 +00:00
|
|
|
/*
|
|
|
|
* Wrapper of getenv() that returns a strdup value. This value is kept
|
|
|
|
* in argv to be freed later.
|
|
|
|
*/
|
|
|
|
static const char *getenv_safe(struct argv_array *argv, const char *name)
|
|
|
|
{
|
|
|
|
const char *value = getenv(name);
|
|
|
|
|
|
|
|
if (!value)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
argv_array_push(argv, value);
|
|
|
|
return argv->argv[argv->argc - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
void setup_git_env(const char *git_dir)
|
2005-10-12 01:47:34 +00:00
|
|
|
{
|
2013-12-05 13:02:45 +00:00
|
|
|
const char *shallow_file;
|
2015-06-11 21:34:59 +00:00
|
|
|
const char *replace_ref_base;
|
2018-03-03 11:35:55 +00:00
|
|
|
struct set_gitdir_args args = { NULL };
|
|
|
|
struct argv_array to_free = ARGV_ARRAY_INIT;
|
|
|
|
|
|
|
|
args.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT);
|
|
|
|
args.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT);
|
|
|
|
args.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT);
|
|
|
|
args.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);
|
2018-03-03 11:35:57 +00:00
|
|
|
args.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT);
|
2018-03-03 11:35:55 +00:00
|
|
|
repo_set_gitdir(the_repository, git_dir, &args);
|
|
|
|
argv_array_clear(&to_free);
|
2013-08-31 01:04:14 +00:00
|
|
|
|
2009-11-18 06:50:58 +00:00
|
|
|
if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
|
2018-07-18 20:45:20 +00:00
|
|
|
read_replace_refs = 0;
|
2015-06-11 21:34:59 +00:00
|
|
|
replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
|
2017-09-05 13:04:57 +00:00
|
|
|
free(git_replace_ref_base);
|
2015-06-11 21:34:59 +00:00
|
|
|
git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
|
|
|
|
: "refs/replace/");
|
2018-02-14 18:59:55 +00:00
|
|
|
free(git_namespace);
|
|
|
|
git_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
|
2013-12-05 13:02:45 +00:00
|
|
|
shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
|
|
|
|
if (shallow_file)
|
2018-05-17 22:51:43 +00:00
|
|
|
set_alternate_shallow_file(the_repository, shallow_file, 0);
|
2006-12-14 22:41:17 +00:00
|
|
|
}
|
|
|
|
|
2007-01-07 10:00:28 +00:00
|
|
|
int is_bare_repository(void)
|
2006-12-14 22:41:17 +00:00
|
|
|
{
|
Clean up work-tree handling
The old version of work-tree support was an unholy mess, barely readable,
and not to the point.
For example, why do you have to provide a worktree, when it is not used?
As in "git status". Now it works.
Another riddle was: if you can have work trees inside the git dir, why
are some programs complaining that they need a work tree?
IOW it is allowed to call
$ git --git-dir=../ --work-tree=. bla
when you really want to. In this case, you are both in the git directory
and in the working tree. So, programs have to actually test for the right
thing, namely if they are inside a working tree, and not if they are
inside a git directory.
Also, GIT_DIR=../.git should behave the same as if no GIT_DIR was
specified, unless there is a repository in the current working directory.
It does now.
The logic to determine if a repository is bare, or has a work tree
(tertium non datur), is this:
--work-tree=bla overrides GIT_WORK_TREE, which overrides core.bare = true,
which overrides core.worktree, which overrides GIT_DIR/.. when GIT_DIR
ends in /.git, which overrides the directory in which .git/ was found.
In related news, a long standing bug was fixed: when in .git/bla/x.git/,
which is a bare repository, git formerly assumed ../.. to be the
appropriate git dir. This problem was reported by Shawn Pearce to have
caused much pain, where a colleague mistakenly ran "git init" in "/" a
long time ago, and bare repositories just would not work.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-08-01 00:30:14 +00:00
|
|
|
/* if core.bare is not 'false', let's see if there is a work tree */
|
|
|
|
return is_bare_repository_cfg && !get_git_work_tree();
|
2005-10-12 01:47:34 +00:00
|
|
|
}
|
|
|
|
|
config: only read .git/config from configured repos
When git_config() runs, it looks in the system, user-wide,
and repo-level config files. It gets the latter by calling
git_pathdup(), which in turn calls get_git_dir(). If we
haven't set up the git repository yet, this may simply
return ".git", and we will look at ".git/config". This
seems like it would be helpful (presumably we haven't set up
the repository yet, so it tries to find it), but it turns
out to be a bad idea for a few reasons:
- it's not sufficient, and therefore hides bugs in a
confusing way. Config will be respected if commands are
run from the top-level of the working tree, but not from
a subdirectory.
- it's not always true that we haven't set up the
repository _yet_; we may not want to do it at all. For
instance, if you run "git init /some/path" from inside
another repository, it should not load config from the
existing repository.
- there might be a path ".git/config", but it is not the
actual repository we would find via setup_git_directory().
This may happen, e.g., if you are storing a git
repository inside another git repository, but have
munged one of the files in such a way that the
inner repository is not valid (e.g., by removing HEAD).
We have at least two bugs of the second type in git-init,
introduced by ae5f677 (lazily load core.sharedrepository,
2016-03-11). It causes init to use git_configset(), which
loads all of the config, including values from the current
repo (if any). This shows up in two ways:
1. If we happen to be in an existing repository directory,
we'll read and respect core.sharedrepository from it,
even though it should have no bearing on the new
repository. A new test in t1301 covers this.
2. Similarly, if we're in an existing repo that sets
core.logallrefupdates, that will cause init to fail to
set it in a newly created repository (because it thinks
that the user's templates already did so). A new test
in t0001 covers this.
We also need to adjust an existing test in t1302, which
gives another example of why this patch is an improvement.
That test creates an embedded repository with a bogus
core.repositoryformatversion of "99". It wants to make sure
that we actually stop at the bogus repo rather than
continuing upward to find the outer repo. So it checks that
"git config core.repositoryformatversion" returns 99. But
that only works because we blindly read ".git/config", even
though we _know_ we're in a repository whose vintage we do
not understand.
After this patch, we avoid reading config from the unknown
vintage repository at all, which is a safer choice. But we
need to tweak the test, since core.repositoryformatversion
will not return 99; it will claim that it could not find the
variable at all.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-13 03:24:15 +00:00
|
|
|
int have_git_dir(void)
|
|
|
|
{
|
|
|
|
return startup_info->have_repository
|
2017-06-22 18:43:33 +00:00
|
|
|
|| the_repository->gitdir;
|
config: only read .git/config from configured repos
When git_config() runs, it looks in the system, user-wide,
and repo-level config files. It gets the latter by calling
git_pathdup(), which in turn calls get_git_dir(). If we
haven't set up the git repository yet, this may simply
return ".git", and we will look at ".git/config". This
seems like it would be helpful (presumably we haven't set up
the repository yet, so it tries to find it), but it turns
out to be a bad idea for a few reasons:
- it's not sufficient, and therefore hides bugs in a
confusing way. Config will be respected if commands are
run from the top-level of the working tree, but not from
a subdirectory.
- it's not always true that we haven't set up the
repository _yet_; we may not want to do it at all. For
instance, if you run "git init /some/path" from inside
another repository, it should not load config from the
existing repository.
- there might be a path ".git/config", but it is not the
actual repository we would find via setup_git_directory().
This may happen, e.g., if you are storing a git
repository inside another git repository, but have
munged one of the files in such a way that the
inner repository is not valid (e.g., by removing HEAD).
We have at least two bugs of the second type in git-init,
introduced by ae5f677 (lazily load core.sharedrepository,
2016-03-11). It causes init to use git_configset(), which
loads all of the config, including values from the current
repo (if any). This shows up in two ways:
1. If we happen to be in an existing repository directory,
we'll read and respect core.sharedrepository from it,
even though it should have no bearing on the new
repository. A new test in t1301 covers this.
2. Similarly, if we're in an existing repo that sets
core.logallrefupdates, that will cause init to fail to
set it in a newly created repository (because it thinks
that the user's templates already did so). A new test
in t0001 covers this.
We also need to adjust an existing test in t1302, which
gives another example of why this patch is an improvement.
That test creates an embedded repository with a bogus
core.repositoryformatversion of "99". It wants to make sure
that we actually stop at the bogus repo rather than
continuing upward to find the outer repo. So it checks that
"git config core.repositoryformatversion" returns 99. But
that only works because we blindly read ".git/config", even
though we _know_ we're in a repository whose vintage we do
not understand.
After this patch, we avoid reading config from the unknown
vintage repository at all, which is a safer choice. But we
need to tweak the test, since core.repositoryformatversion
will not return 99; it will claim that it could not find the
variable at all.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-13 03:24:15 +00:00
|
|
|
}
|
|
|
|
|
2006-08-23 10:39:11 +00:00
|
|
|
const char *get_git_dir(void)
|
2005-10-12 01:47:34 +00:00
|
|
|
{
|
2017-06-22 18:43:33 +00:00
|
|
|
if (!the_repository->gitdir)
|
2017-06-20 19:19:32 +00:00
|
|
|
BUG("git environment hasn't been setup");
|
2017-06-22 18:43:33 +00:00
|
|
|
return the_repository->gitdir;
|
2005-10-12 01:47:34 +00:00
|
|
|
}
|
|
|
|
|
$GIT_COMMON_DIR: a new environment variable
This variable is intended to support multiple working directories
attached to a repository. Such a repository may have a main working
directory, created by either "git init" or "git clone" and one or more
linked working directories. These working directories and the main
repository share the same repository directory.
In linked working directories, $GIT_COMMON_DIR must be defined to point
to the real repository directory and $GIT_DIR points to an unused
subdirectory inside $GIT_COMMON_DIR. File locations inside the
repository are reorganized from the linked worktree view point:
- worktree-specific such as HEAD, logs/HEAD, index, other top-level
refs and unrecognized files are from $GIT_DIR.
- the rest like objects, refs, info, hooks, packed-refs, shallow...
are from $GIT_COMMON_DIR (except info/sparse-checkout, but that's
a separate patch)
Scripts are supposed to retrieve paths in $GIT_DIR with "git rev-parse
--git-path", which will take care of "$GIT_DIR vs $GIT_COMMON_DIR"
business.
The redirection is done by git_path(), git_pathdup() and
strbuf_git_path(). The selected list of paths goes to $GIT_COMMON_DIR,
not the other way around in case a developer adds a new
worktree-specific file and it's accidentally promoted to be shared
across repositories (this includes unknown files added by third party
commands)
The list of known files that belong to $GIT_DIR are:
ADD_EDIT.patch BISECT_ANCESTORS_OK BISECT_EXPECTED_REV BISECT_LOG
BISECT_NAMES CHERRY_PICK_HEAD COMMIT_MSG FETCH_HEAD HEAD MERGE_HEAD
MERGE_MODE MERGE_RR NOTES_EDITMSG NOTES_MERGE_WORKTREE ORIG_HEAD
REVERT_HEAD SQUASH_MSG TAG_EDITMSG fast_import_crash_* logs/HEAD
next-index-* rebase-apply rebase-merge rsync-refs-* sequencer/*
shallow_*
Path mapping is NOT done for git_path_submodule(). Multi-checkouts are
not supported as submodules.
Helped-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-30 08:24:36 +00:00
|
|
|
const char *get_git_common_dir(void)
|
|
|
|
{
|
2017-06-22 18:43:33 +00:00
|
|
|
if (!the_repository->commondir)
|
2017-06-20 19:19:32 +00:00
|
|
|
BUG("git environment hasn't been setup");
|
2017-06-22 18:43:33 +00:00
|
|
|
return the_repository->commondir;
|
$GIT_COMMON_DIR: a new environment variable
This variable is intended to support multiple working directories
attached to a repository. Such a repository may have a main working
directory, created by either "git init" or "git clone" and one or more
linked working directories. These working directories and the main
repository share the same repository directory.
In linked working directories, $GIT_COMMON_DIR must be defined to point
to the real repository directory and $GIT_DIR points to an unused
subdirectory inside $GIT_COMMON_DIR. File locations inside the
repository are reorganized from the linked worktree view point:
- worktree-specific such as HEAD, logs/HEAD, index, other top-level
refs and unrecognized files are from $GIT_DIR.
- the rest like objects, refs, info, hooks, packed-refs, shallow...
are from $GIT_COMMON_DIR (except info/sparse-checkout, but that's
a separate patch)
Scripts are supposed to retrieve paths in $GIT_DIR with "git rev-parse
--git-path", which will take care of "$GIT_DIR vs $GIT_COMMON_DIR"
business.
The redirection is done by git_path(), git_pathdup() and
strbuf_git_path(). The selected list of paths goes to $GIT_COMMON_DIR,
not the other way around in case a developer adds a new
worktree-specific file and it's accidentally promoted to be shared
across repositories (this includes unknown files added by third party
commands)
The list of known files that belong to $GIT_DIR are:
ADD_EDIT.patch BISECT_ANCESTORS_OK BISECT_EXPECTED_REV BISECT_LOG
BISECT_NAMES CHERRY_PICK_HEAD COMMIT_MSG FETCH_HEAD HEAD MERGE_HEAD
MERGE_MODE MERGE_RR NOTES_EDITMSG NOTES_MERGE_WORKTREE ORIG_HEAD
REVERT_HEAD SQUASH_MSG TAG_EDITMSG fast_import_crash_* logs/HEAD
next-index-* rebase-apply rebase-merge rsync-refs-* sequencer/*
shallow_*
Path mapping is NOT done for git_path_submodule(). Multi-checkouts are
not supported as submodules.
Helped-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-30 08:24:36 +00:00
|
|
|
}
|
|
|
|
|
ref namespaces: infrastructure
Add support for dividing the refs of a single repository into multiple
namespaces, each of which can have its own branches, tags, and HEAD.
Git can expose each namespace as an independent repository to pull from
and push to, while sharing the object store, and exposing all the refs
to operations such as git-gc.
Storing multiple repositories as namespaces of a single repository
avoids storing duplicate copies of the same objects, such as when
storing multiple branches of the same source. The alternates mechanism
provides similar support for avoiding duplicates, but alternates do not
prevent duplication between new objects added to the repositories
without ongoing maintenance, while namespaces do.
To specify a namespace, set the GIT_NAMESPACE environment variable to
the namespace. For each ref namespace, git stores the corresponding
refs in a directory under refs/namespaces/. For example,
GIT_NAMESPACE=foo will store refs under refs/namespaces/foo/. You can
also specify namespaces via the --namespace option to git.
Note that namespaces which include a / will expand to a hierarchy of
namespaces; for example, GIT_NAMESPACE=foo/bar will store refs under
refs/namespaces/foo/refs/namespaces/bar/. This makes paths in
GIT_NAMESPACE behave hierarchically, so that cloning with
GIT_NAMESPACE=foo/bar produces the same result as cloning with
GIT_NAMESPACE=foo and cloning from that repo with GIT_NAMESPACE=bar. It
also avoids ambiguity with strange namespace paths such as
foo/refs/heads/, which could otherwise generate directory/file conflicts
within the refs directory.
Add the infrastructure for ref namespaces: handle the GIT_NAMESPACE
environment variable and --namespace option, and support iterating over
refs in a namespace.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-07-05 17:54:44 +00:00
|
|
|
const char *get_git_namespace(void)
|
|
|
|
{
|
2018-02-14 18:59:55 +00:00
|
|
|
if (!git_namespace)
|
2017-06-20 19:19:32 +00:00
|
|
|
BUG("git environment hasn't been setup");
|
2018-02-14 18:59:55 +00:00
|
|
|
return git_namespace;
|
ref namespaces: infrastructure
Add support for dividing the refs of a single repository into multiple
namespaces, each of which can have its own branches, tags, and HEAD.
Git can expose each namespace as an independent repository to pull from
and push to, while sharing the object store, and exposing all the refs
to operations such as git-gc.
Storing multiple repositories as namespaces of a single repository
avoids storing duplicate copies of the same objects, such as when
storing multiple branches of the same source. The alternates mechanism
provides similar support for avoiding duplicates, but alternates do not
prevent duplication between new objects added to the repositories
without ongoing maintenance, while namespaces do.
To specify a namespace, set the GIT_NAMESPACE environment variable to
the namespace. For each ref namespace, git stores the corresponding
refs in a directory under refs/namespaces/. For example,
GIT_NAMESPACE=foo will store refs under refs/namespaces/foo/. You can
also specify namespaces via the --namespace option to git.
Note that namespaces which include a / will expand to a hierarchy of
namespaces; for example, GIT_NAMESPACE=foo/bar will store refs under
refs/namespaces/foo/refs/namespaces/bar/. This makes paths in
GIT_NAMESPACE behave hierarchically, so that cloning with
GIT_NAMESPACE=foo/bar produces the same result as cloning with
GIT_NAMESPACE=foo and cloning from that repo with GIT_NAMESPACE=bar. It
also avoids ambiguity with strange namespace paths such as
foo/refs/heads/, which could otherwise generate directory/file conflicts
within the refs directory.
Add the infrastructure for ref namespaces: handle the GIT_NAMESPACE
environment variable and --namespace option, and support iterating over
refs in a namespace.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-07-05 17:54:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *strip_namespace(const char *namespaced_ref)
|
|
|
|
{
|
2017-06-20 19:19:34 +00:00
|
|
|
const char *out;
|
|
|
|
if (skip_prefix(namespaced_ref, get_git_namespace(), &out))
|
|
|
|
return out;
|
|
|
|
return NULL;
|
ref namespaces: infrastructure
Add support for dividing the refs of a single repository into multiple
namespaces, each of which can have its own branches, tags, and HEAD.
Git can expose each namespace as an independent repository to pull from
and push to, while sharing the object store, and exposing all the refs
to operations such as git-gc.
Storing multiple repositories as namespaces of a single repository
avoids storing duplicate copies of the same objects, such as when
storing multiple branches of the same source. The alternates mechanism
provides similar support for avoiding duplicates, but alternates do not
prevent duplication between new objects added to the repositories
without ongoing maintenance, while namespaces do.
To specify a namespace, set the GIT_NAMESPACE environment variable to
the namespace. For each ref namespace, git stores the corresponding
refs in a directory under refs/namespaces/. For example,
GIT_NAMESPACE=foo will store refs under refs/namespaces/foo/. You can
also specify namespaces via the --namespace option to git.
Note that namespaces which include a / will expand to a hierarchy of
namespaces; for example, GIT_NAMESPACE=foo/bar will store refs under
refs/namespaces/foo/refs/namespaces/bar/. This makes paths in
GIT_NAMESPACE behave hierarchically, so that cloning with
GIT_NAMESPACE=foo/bar produces the same result as cloning with
GIT_NAMESPACE=foo and cloning from that repo with GIT_NAMESPACE=bar. It
also avoids ambiguity with strange namespace paths such as
foo/refs/heads/, which could otherwise generate directory/file conflicts
within the refs directory.
Add the infrastructure for ref namespaces: handle the GIT_NAMESPACE
environment variable and --namespace option, and support iterating over
refs in a namespace.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-07-05 17:54:44 +00:00
|
|
|
}
|
|
|
|
|
2016-10-07 18:18:48 +00:00
|
|
|
const char *get_super_prefix(void)
|
|
|
|
{
|
|
|
|
static int initialized;
|
|
|
|
if (!initialized) {
|
2019-01-11 22:15:00 +00:00
|
|
|
super_prefix = xstrdup_or_null(getenv(GIT_SUPER_PREFIX_ENVIRONMENT));
|
2016-10-07 18:18:48 +00:00
|
|
|
initialized = 1;
|
|
|
|
}
|
|
|
|
return super_prefix;
|
|
|
|
}
|
|
|
|
|
2008-04-27 17:39:21 +00:00
|
|
|
static int git_work_tree_initialized;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note. This works only before you used a work tree. This was added
|
|
|
|
* primarily to support git-clone to work in a new repository it just
|
|
|
|
* created, and is not meant to flip between different work trees.
|
|
|
|
*/
|
|
|
|
void set_git_work_tree(const char *new_work_tree)
|
|
|
|
{
|
2010-11-26 15:32:40 +00:00
|
|
|
if (git_work_tree_initialized) {
|
2011-03-17 11:26:46 +00:00
|
|
|
new_work_tree = real_path(new_work_tree);
|
2017-06-22 18:43:34 +00:00
|
|
|
if (strcmp(new_work_tree, the_repository->worktree))
|
2010-11-26 15:32:40 +00:00
|
|
|
die("internal error: work tree has already been set\n"
|
|
|
|
"Current worktree: %s\nNew worktree: %s",
|
2017-06-22 18:43:34 +00:00
|
|
|
the_repository->worktree, new_work_tree);
|
2010-11-26 15:32:40 +00:00
|
|
|
return;
|
|
|
|
}
|
2008-04-27 17:39:21 +00:00
|
|
|
git_work_tree_initialized = 1;
|
2017-06-22 18:43:34 +00:00
|
|
|
repo_set_worktree(the_repository, new_work_tree);
|
2008-04-27 17:39:21 +00:00
|
|
|
}
|
|
|
|
|
Clean up work-tree handling
The old version of work-tree support was an unholy mess, barely readable,
and not to the point.
For example, why do you have to provide a worktree, when it is not used?
As in "git status". Now it works.
Another riddle was: if you can have work trees inside the git dir, why
are some programs complaining that they need a work tree?
IOW it is allowed to call
$ git --git-dir=../ --work-tree=. bla
when you really want to. In this case, you are both in the git directory
and in the working tree. So, programs have to actually test for the right
thing, namely if they are inside a working tree, and not if they are
inside a git directory.
Also, GIT_DIR=../.git should behave the same as if no GIT_DIR was
specified, unless there is a repository in the current working directory.
It does now.
The logic to determine if a repository is bare, or has a work tree
(tertium non datur), is this:
--work-tree=bla overrides GIT_WORK_TREE, which overrides core.bare = true,
which overrides core.worktree, which overrides GIT_DIR/.. when GIT_DIR
ends in /.git, which overrides the directory in which .git/ was found.
In related news, a long standing bug was fixed: when in .git/bla/x.git/,
which is a bare repository, git formerly assumed ../.. to be the
appropriate git dir. This problem was reported by Shawn Pearce to have
caused much pain, where a colleague mistakenly ran "git init" in "/" a
long time ago, and bare repositories just would not work.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-08-01 00:30:14 +00:00
|
|
|
const char *get_git_work_tree(void)
|
|
|
|
{
|
2017-06-22 18:43:34 +00:00
|
|
|
return the_repository->worktree;
|
Clean up work-tree handling
The old version of work-tree support was an unholy mess, barely readable,
and not to the point.
For example, why do you have to provide a worktree, when it is not used?
As in "git status". Now it works.
Another riddle was: if you can have work trees inside the git dir, why
are some programs complaining that they need a work tree?
IOW it is allowed to call
$ git --git-dir=../ --work-tree=. bla
when you really want to. In this case, you are both in the git directory
and in the working tree. So, programs have to actually test for the right
thing, namely if they are inside a working tree, and not if they are
inside a git directory.
Also, GIT_DIR=../.git should behave the same as if no GIT_DIR was
specified, unless there is a repository in the current working directory.
It does now.
The logic to determine if a repository is bare, or has a work tree
(tertium non datur), is this:
--work-tree=bla overrides GIT_WORK_TREE, which overrides core.bare = true,
which overrides core.worktree, which overrides GIT_DIR/.. when GIT_DIR
ends in /.git, which overrides the directory in which .git/ was found.
In related news, a long standing bug was fixed: when in .git/bla/x.git/,
which is a bare repository, git formerly assumed ../.. to be the
appropriate git dir. This problem was reported by Shawn Pearce to have
caused much pain, where a colleague mistakenly ran "git init" in "/" a
long time ago, and bare repositories just would not work.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-08-01 00:30:14 +00:00
|
|
|
}
|
|
|
|
|
2005-10-12 01:47:34 +00:00
|
|
|
char *get_object_directory(void)
|
|
|
|
{
|
sha1-file: use an object_directory for the main object dir
Our handling of alternate object directories is needlessly different
from the main object directory. As a result, many places in the code
basically look like this:
do_something(r->objects->objdir);
for (odb = r->objects->alt_odb_list; odb; odb = odb->next)
do_something(odb->path);
That gets annoying when do_something() is non-trivial, and we've
resorted to gross hacks like creating fake alternates (see
find_short_object_filename()).
Instead, let's give each raw_object_store a unified list of
object_directory structs. The first will be the main store, and
everything after is an alternate. Very few callers even care about the
distinction, and can just loop over the whole list (and those who care
can just treat the first element differently).
A few observations:
- we don't need r->objects->objectdir anymore, and can just
mechanically convert that to r->objects->odb->path
- object_directory's path field needs to become a real pointer rather
than a FLEX_ARRAY, in order to fill it with expand_base_dir()
- we'll call prepare_alt_odb() earlier in many functions (i.e.,
outside of the loop). This may result in us calling it even when our
function would be satisfied looking only at the main odb.
But this doesn't matter in practice. It's not a very expensive
operation in the first place, and in the majority of cases it will
be a noop. We call it already (and cache its results) in
prepare_packed_git(), and we'll generally check packs before loose
objects. So essentially every program is going to call it
immediately once per program.
Arguably we should just prepare_alt_odb() immediately upon setting
up the repository's object directory, which would save us sprinkling
calls throughout the code base (and forgetting to do so has been a
source of subtle bugs in the past). But I've stopped short of that
here, since there are already a lot of other moving parts in this
patch.
- Most call sites just get shorter. The check_and_freshen() functions
are an exception, because they have entry points to handle local and
nonlocal directories separately.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-12 14:50:39 +00:00
|
|
|
if (!the_repository->objects->odb)
|
2017-06-20 19:19:32 +00:00
|
|
|
BUG("git environment hasn't been setup");
|
sha1-file: use an object_directory for the main object dir
Our handling of alternate object directories is needlessly different
from the main object directory. As a result, many places in the code
basically look like this:
do_something(r->objects->objdir);
for (odb = r->objects->alt_odb_list; odb; odb = odb->next)
do_something(odb->path);
That gets annoying when do_something() is non-trivial, and we've
resorted to gross hacks like creating fake alternates (see
find_short_object_filename()).
Instead, let's give each raw_object_store a unified list of
object_directory structs. The first will be the main store, and
everything after is an alternate. Very few callers even care about the
distinction, and can just loop over the whole list (and those who care
can just treat the first element differently).
A few observations:
- we don't need r->objects->objectdir anymore, and can just
mechanically convert that to r->objects->odb->path
- object_directory's path field needs to become a real pointer rather
than a FLEX_ARRAY, in order to fill it with expand_base_dir()
- we'll call prepare_alt_odb() earlier in many functions (i.e.,
outside of the loop). This may result in us calling it even when our
function would be satisfied looking only at the main odb.
But this doesn't matter in practice. It's not a very expensive
operation in the first place, and in the majority of cases it will
be a noop. We call it already (and cache its results) in
prepare_packed_git(), and we'll generally check packs before loose
objects. So essentially every program is going to call it
immediately once per program.
Arguably we should just prepare_alt_odb() immediately upon setting
up the repository's object directory, which would save us sprinkling
calls throughout the code base (and forgetting to do so has been a
source of subtle bugs in the past). But I've stopped short of that
here, since there are already a lot of other moving parts in this
patch.
- Most call sites just get shorter. The check_and_freshen() functions
are an exception, because they have entry points to handle local and
nonlocal directories separately.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-12 14:50:39 +00:00
|
|
|
return the_repository->objects->odb->path;
|
2005-10-12 01:47:34 +00:00
|
|
|
}
|
|
|
|
|
2018-02-14 18:59:53 +00:00
|
|
|
int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)
|
2010-11-06 11:45:38 +00:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
/*
|
|
|
|
* we let the umask do its job, don't try to be more
|
|
|
|
* restrictive except to remove write permission.
|
|
|
|
*/
|
|
|
|
int mode = 0444;
|
2018-02-14 18:59:53 +00:00
|
|
|
git_path_buf(temp_filename, "objects/%s", pattern);
|
|
|
|
fd = git_mkstemp_mode(temp_filename->buf, mode);
|
2010-11-06 11:45:38 +00:00
|
|
|
if (0 <= fd)
|
|
|
|
return fd;
|
|
|
|
|
|
|
|
/* slow path */
|
2018-02-14 18:59:53 +00:00
|
|
|
/* some mkstemp implementations erase temp_filename on failure */
|
|
|
|
git_path_buf(temp_filename, "objects/%s", pattern);
|
|
|
|
safe_create_leading_directories(temp_filename->buf);
|
|
|
|
return xmkstemp_mode(temp_filename->buf, mode);
|
2010-11-06 11:45:38 +00:00
|
|
|
}
|
|
|
|
|
2017-03-16 14:27:12 +00:00
|
|
|
int odb_pack_keep(const char *name)
|
2010-11-06 11:45:38 +00:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
|
|
|
|
if (0 <= fd)
|
|
|
|
return fd;
|
|
|
|
|
|
|
|
/* slow path */
|
2017-03-16 14:27:12 +00:00
|
|
|
safe_create_leading_directories_const(name);
|
2010-11-06 11:45:38 +00:00
|
|
|
return open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
|
|
|
|
}
|
|
|
|
|
2005-10-12 01:47:34 +00:00
|
|
|
char *get_index_file(void)
|
|
|
|
{
|
2017-06-22 18:43:33 +00:00
|
|
|
if (!the_repository->index_file)
|
2017-06-20 19:19:32 +00:00
|
|
|
BUG("git environment hasn't been setup");
|
2017-06-22 18:43:33 +00:00
|
|
|
return the_repository->index_file;
|
2005-10-12 01:47:34 +00:00
|
|
|
}
|
|
|
|
|
2018-05-17 22:51:50 +00:00
|
|
|
char *get_graft_file(struct repository *r)
|
2005-10-12 01:47:34 +00:00
|
|
|
{
|
2018-05-17 22:51:50 +00:00
|
|
|
if (!r->graft_file)
|
2017-06-20 19:19:32 +00:00
|
|
|
BUG("git environment hasn't been setup");
|
2018-05-17 22:51:50 +00:00
|
|
|
return r->graft_file;
|
2005-10-12 01:47:34 +00:00
|
|
|
}
|
2007-08-01 00:29:38 +00:00
|
|
|
|
set_work_tree: use chdir_notify
When we change to the top of the working tree, we manually
re-adjust $GIT_DIR and call set_git_dir() again, in order to
update any relative git-dir we'd compute earlier.
Instead of the work-tree code having to know to call the
git-dir code, let's use the new chdir_notify interface.
There are two spots that need updating, with a few
subtleties in each:
1. the set_git_dir() code needs to chdir_notify_register()
so it can be told when to update its path.
Technically we could push this down into repo_set_gitdir(),
so that even repository structs besides the_repository
could benefit from this. But that opens up a lot of
complications:
- we'd still need to touch set_git_dir(), because it
does some other setup (like setting $GIT_DIR in the
environment)
- submodules using other repository structs get
cleaned up, which means we'd need to remove them
from the chdir_notify list
- it's unlikely to fix any bugs, since we shouldn't
generally chdir() in the middle of working on a
submodule
2. setup_work_tree now needs to call chdir_notify(), and
can lose its manual set_git_dir() call.
Note that at first glance it looks like this undoes the
absolute-to-relative optimization added by 044bbbcb63
(Make git_dir a path relative to work_tree in
setup_work_tree(), 2008-06-19). But for the most part
that optimization was just _undoing_ the
relative-to-absolute conversion which the function was
doing earlier (and which is now gone).
It is true that if you already have an absolute git_dir
that the setup_work_tree() function will no longer make
it relative as a side effect. But:
- we generally do have relative git-dir's due to the
way the discovery code works
- if we really care about making git-dir's relative
when possible, then we should be relativizing them
earlier (e.g., when we see an absolute $GIT_DIR we
could turn it relative, whether we are going to
chdir into a worktree or not). That would cover all
cases, including ones that 044bbbcb63 did not.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-03-30 18:35:08 +00:00
|
|
|
static void set_git_dir_1(const char *path)
|
2007-08-01 00:29:38 +00:00
|
|
|
{
|
|
|
|
if (setenv(GIT_DIR_ENVIRONMENT, path, 1))
|
2018-07-21 07:49:31 +00:00
|
|
|
die(_("could not set GIT_DIR to '%s'"), path);
|
2018-03-03 11:35:55 +00:00
|
|
|
setup_git_env(path);
|
2007-08-01 00:29:38 +00:00
|
|
|
}
|
2010-11-02 19:59:07 +00:00
|
|
|
|
set_work_tree: use chdir_notify
When we change to the top of the working tree, we manually
re-adjust $GIT_DIR and call set_git_dir() again, in order to
update any relative git-dir we'd compute earlier.
Instead of the work-tree code having to know to call the
git-dir code, let's use the new chdir_notify interface.
There are two spots that need updating, with a few
subtleties in each:
1. the set_git_dir() code needs to chdir_notify_register()
so it can be told when to update its path.
Technically we could push this down into repo_set_gitdir(),
so that even repository structs besides the_repository
could benefit from this. But that opens up a lot of
complications:
- we'd still need to touch set_git_dir(), because it
does some other setup (like setting $GIT_DIR in the
environment)
- submodules using other repository structs get
cleaned up, which means we'd need to remove them
from the chdir_notify list
- it's unlikely to fix any bugs, since we shouldn't
generally chdir() in the middle of working on a
submodule
2. setup_work_tree now needs to call chdir_notify(), and
can lose its manual set_git_dir() call.
Note that at first glance it looks like this undoes the
absolute-to-relative optimization added by 044bbbcb63
(Make git_dir a path relative to work_tree in
setup_work_tree(), 2008-06-19). But for the most part
that optimization was just _undoing_ the
relative-to-absolute conversion which the function was
doing earlier (and which is now gone).
It is true that if you already have an absolute git_dir
that the setup_work_tree() function will no longer make
it relative as a side effect. But:
- we generally do have relative git-dir's due to the
way the discovery code works
- if we really care about making git-dir's relative
when possible, then we should be relativizing them
earlier (e.g., when we see an absolute $GIT_DIR we
could turn it relative, whether we are going to
chdir into a worktree or not). That would cover all
cases, including ones that 044bbbcb63 did not.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-03-30 18:35:08 +00:00
|
|
|
static void update_relative_gitdir(const char *name,
|
|
|
|
const char *old_cwd,
|
|
|
|
const char *new_cwd,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
char *path = reparent_relative_path(old_cwd, new_cwd, get_git_dir());
|
|
|
|
trace_printf_key(&trace_setup_key,
|
|
|
|
"setup: move $GIT_DIR to '%s'",
|
|
|
|
path);
|
|
|
|
set_git_dir_1(path);
|
|
|
|
free(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_git_dir(const char *path)
|
|
|
|
{
|
|
|
|
set_git_dir_1(path);
|
|
|
|
if (!is_absolute_path(path))
|
|
|
|
chdir_notify_register(NULL, update_relative_gitdir, NULL);
|
2007-08-01 00:29:38 +00:00
|
|
|
}
|
2010-11-02 19:59:07 +00:00
|
|
|
|
|
|
|
const char *get_log_output_encoding(void)
|
|
|
|
{
|
|
|
|
return git_log_output_encoding ? git_log_output_encoding
|
|
|
|
: get_commit_output_encoding();
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *get_commit_output_encoding(void)
|
|
|
|
{
|
|
|
|
return git_commit_encoding ? git_commit_encoding : "UTF-8";
|
|
|
|
}
|
2016-03-11 22:36:49 +00:00
|
|
|
|
|
|
|
static int the_shared_repository = PERM_UMASK;
|
lazily load core.sharedrepository
The "shared_repository" config is loaded as part of
check_repository_format_version, but it's not quite like the
other values we check there. Something like
core.repositoryformatversion only makes sense in per-repo
config, but core.sharedrepository can be set in a per-user
config (e.g., to make all "git init" invocations shared by
default).
So it would make more sense as part of git_default_config.
Commit 457f06d (Introduce core.sharedrepository, 2005-12-22)
says:
[...]the config variable is set in the function which
checks the repository format. If this were done in
git_default_config instead, a lot of programs would need
to be modified to call git_config(git_default_config)
first.
This is still the case today, but we have one extra trick up
our sleeve. Now that we have the git_configset
infrastructure, it's not so expensive for us to ask for a
single value. So we can simply lazy-load it on demand.
This should be OK to do in general. There are some problems
with loading config before setup_git_directory() is called,
but we shouldn't be accessing the value before then (if we
were, then it would already be broken, as the variable would
not have been set by check_repository_format_version!). The
trickiest caller is git-init, but it handles the values
manually itself.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-03-11 22:36:53 +00:00
|
|
|
static int need_shared_repository_from_config = 1;
|
2016-03-11 22:36:49 +00:00
|
|
|
|
|
|
|
void set_shared_repository(int value)
|
|
|
|
{
|
|
|
|
the_shared_repository = value;
|
lazily load core.sharedrepository
The "shared_repository" config is loaded as part of
check_repository_format_version, but it's not quite like the
other values we check there. Something like
core.repositoryformatversion only makes sense in per-repo
config, but core.sharedrepository can be set in a per-user
config (e.g., to make all "git init" invocations shared by
default).
So it would make more sense as part of git_default_config.
Commit 457f06d (Introduce core.sharedrepository, 2005-12-22)
says:
[...]the config variable is set in the function which
checks the repository format. If this were done in
git_default_config instead, a lot of programs would need
to be modified to call git_config(git_default_config)
first.
This is still the case today, but we have one extra trick up
our sleeve. Now that we have the git_configset
infrastructure, it's not so expensive for us to ask for a
single value. So we can simply lazy-load it on demand.
This should be OK to do in general. There are some problems
with loading config before setup_git_directory() is called,
but we shouldn't be accessing the value before then (if we
were, then it would already be broken, as the variable would
not have been set by check_repository_format_version!). The
trickiest caller is git-init, but it handles the values
manually itself.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-03-11 22:36:53 +00:00
|
|
|
need_shared_repository_from_config = 0;
|
2016-03-11 22:36:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int get_shared_repository(void)
|
|
|
|
{
|
lazily load core.sharedrepository
The "shared_repository" config is loaded as part of
check_repository_format_version, but it's not quite like the
other values we check there. Something like
core.repositoryformatversion only makes sense in per-repo
config, but core.sharedrepository can be set in a per-user
config (e.g., to make all "git init" invocations shared by
default).
So it would make more sense as part of git_default_config.
Commit 457f06d (Introduce core.sharedrepository, 2005-12-22)
says:
[...]the config variable is set in the function which
checks the repository format. If this were done in
git_default_config instead, a lot of programs would need
to be modified to call git_config(git_default_config)
first.
This is still the case today, but we have one extra trick up
our sleeve. Now that we have the git_configset
infrastructure, it's not so expensive for us to ask for a
single value. So we can simply lazy-load it on demand.
This should be OK to do in general. There are some problems
with loading config before setup_git_directory() is called,
but we shouldn't be accessing the value before then (if we
were, then it would already be broken, as the variable would
not have been set by check_repository_format_version!). The
trickiest caller is git-init, but it handles the values
manually itself.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-03-11 22:36:53 +00:00
|
|
|
if (need_shared_repository_from_config) {
|
|
|
|
const char *var = "core.sharedrepository";
|
|
|
|
const char *value;
|
|
|
|
if (!git_config_get_value(var, &value))
|
|
|
|
the_shared_repository = git_config_perm(var, value);
|
|
|
|
need_shared_repository_from_config = 0;
|
|
|
|
}
|
2016-03-11 22:36:49 +00:00
|
|
|
return the_shared_repository;
|
|
|
|
}
|
2016-09-13 03:24:23 +00:00
|
|
|
|
|
|
|
void reset_shared_repository(void)
|
|
|
|
{
|
|
|
|
need_shared_repository_from_config = 1;
|
|
|
|
}
|
git: add --no-optional-locks option
Some tools like IDEs or fancy editors may periodically run
commands like "git status" in the background to keep track
of the state of the repository. Some of these commands may
refresh the index and write out the result in an
opportunistic way: if they can get the index lock, then they
update the on-disk index with any updates they find. And if
not, then their in-core refresh is lost and just has to be
recomputed by the next caller.
But taking the index lock may conflict with other operations
in the repository. Especially ones that the user is doing
themselves, which _aren't_ opportunistic. In other words,
"git status" knows how to back off when somebody else is
holding the lock, but other commands don't know that status
would be happy to drop the lock if somebody else wanted it.
There are a couple possible solutions:
1. Have some kind of "pseudo-lock" that allows other
commands to tell status that they want the lock.
This is likely to be complicated and error-prone to
implement (and maybe even impossible with just
dotlocks to work from, as it requires some
inter-process communication).
2. Avoid background runs of commands like "git status"
that want to do opportunistic updates, preferring
instead plumbing like diff-files, etc.
This is awkward for a couple of reasons. One is that
"status --porcelain" reports a lot more about the
repository state than is available from individual
plumbing commands. And two is that we actually _do_
want to see the refreshed index. We just don't want to
take a lock or write out the result. Whereas commands
like diff-files expect us to refresh the index
separately and write it to disk so that they can depend
on the result. But that write is exactly what we're
trying to avoid.
3. Ask "status" not to lock or write the index.
This is easy to implement. The big downside is that any
work done in refreshing the index for such a call is
lost when the process exits. So a background process
may end up re-hashing a changed file multiple times
until the user runs a command that does an index
refresh themselves.
This patch implements the option 3. The idea (and the test)
is largely stolen from a Git for Windows patch by Johannes
Schindelin, 67e5ce7f63 (status: offer *not* to lock the
index and update it, 2016-08-12). The twist here is that
instead of making this an option to "git status", it becomes
a "git" option and matching environment variable.
The reason there is two-fold:
1. An environment variable is carried through to
sub-processes. And whether an invocation is a
background process or not should apply to the whole
process tree. So you could do "git --no-optional-locks
foo", and if "foo" is a script or alias that calls
"status", you'll still get the effect.
2. There may be other programs that want the same
treatment.
I've punted here on finding more callers to convert,
since "status" is the obvious one to call as a repeated
background job. But "git diff"'s opportunistic refresh
of the index may be a good candidate.
The test is taken from 67e5ce7f63, and it's worth repeating
Johannes's explanation:
Note that the regression test added in this commit does
not *really* verify that no index.lock file was written;
that test is not possible in a portable way. Instead, we
verify that .git/index is rewritten *only* when `git
status` is run without `--no-optional-locks`.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-09-27 06:54:30 +00:00
|
|
|
|
|
|
|
int use_optional_locks(void)
|
|
|
|
{
|
|
|
|
return git_env_bool(GIT_OPTIONAL_LOCKS_ENVIRONMENT, 1);
|
|
|
|
}
|
2017-12-03 21:27:39 +00:00
|
|
|
|
|
|
|
int print_sha1_ellipsis(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Determine if the calling environment contains the variable
|
|
|
|
* GIT_PRINT_SHA1_ELLIPSIS set to "yes".
|
|
|
|
*/
|
|
|
|
static int cached_result = -1; /* unknown */
|
|
|
|
|
|
|
|
if (cached_result < 0) {
|
|
|
|
const char *v = getenv("GIT_PRINT_SHA1_ELLIPSIS");
|
|
|
|
cached_result = (v && !strcasecmp(v, "yes"));
|
|
|
|
}
|
|
|
|
return cached_result;
|
|
|
|
}
|