Coverage Report

Created: 2023-11-19 07:08

/src/git/environment.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * We put all the git config variables in this same object
3
 * file, so that programs can link against the config parser
4
 * without having to link against all the rest of git.
5
 *
6
 * In particular, no need to bring in libz etc unless needed,
7
 * even if you might want to know where the git directory etc
8
 * are.
9
 */
10
#include "git-compat-util.h"
11
#include "abspath.h"
12
#include "branch.h"
13
#include "convert.h"
14
#include "environment.h"
15
#include "gettext.h"
16
#include "repository.h"
17
#include "config.h"
18
#include "refs.h"
19
#include "fmt-merge-msg.h"
20
#include "commit.h"
21
#include "strvec.h"
22
#include "object-file.h"
23
#include "object-store-ll.h"
24
#include "path.h"
25
#include "replace-object.h"
26
#include "tmp-objdir.h"
27
#include "chdir-notify.h"
28
#include "setup.h"
29
#include "shallow.h"
30
#include "trace.h"
31
#include "write-or-die.h"
32
33
int trust_executable_bit = 1;
34
int trust_ctime = 1;
35
int check_stat = 1;
36
int has_symlinks = 1;
37
int minimum_abbrev = 4, default_abbrev = -1;
38
int ignore_case;
39
int assume_unchanged;
40
int prefer_symlink_refs;
41
int is_bare_repository_cfg = -1; /* unspecified */
42
int warn_ambiguous_refs = 1;
43
int warn_on_object_refname_ambiguity = 1;
44
int repository_format_precious_objects;
45
const char *git_commit_encoding;
46
const char *git_log_output_encoding;
47
char *apply_default_whitespace;
48
char *apply_default_ignorewhitespace;
49
const char *git_attributes_file;
50
const char *git_hooks_path;
51
int zlib_compression_level = Z_BEST_SPEED;
52
int pack_compression_level = Z_DEFAULT_COMPRESSION;
53
int fsync_object_files = -1;
54
int use_fsync = -1;
55
enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT;
56
enum fsync_component fsync_components = FSYNC_COMPONENTS_DEFAULT;
57
size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
58
size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
59
size_t delta_base_cache_limit = 96 * 1024 * 1024;
60
unsigned long big_file_threshold = 512 * 1024 * 1024;
61
const char *editor_program;
62
const char *askpass_program;
63
const char *excludes_file;
64
enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
65
enum eol core_eol = EOL_UNSET;
66
int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
67
char *check_roundtrip_encoding = "SHIFT-JIS";
68
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
69
enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
70
enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
71
#ifndef OBJECT_CREATION_MODE
72
#define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS
73
#endif
74
enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
75
char *notes_ref_name;
76
int grafts_keep_true_parents;
77
int core_apply_sparse_checkout;
78
int core_sparse_checkout_cone;
79
int sparse_expect_files_outside_of_patterns;
80
int merge_log_config = -1;
81
int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
82
unsigned long pack_size_limit_cfg;
83
enum log_refs_config log_all_ref_updates = LOG_REFS_UNSET;
84
int max_allowed_tree_depth =
85
#ifdef _MSC_VER
86
  /*
87
   * When traversing into too-deep trees, Visual C-compiled Git seems to
88
   * run into some internal stack overflow detection in the
89
   * `RtlpAllocateHeap()` function that is called from within
90
   * `git_inflate_init()`'s call tree. The following value seems to be
91
   * low enough to avoid that by letting Git exit with an error before
92
   * the stack overflow can occur.
93
   */
94
  512;
95
#else
96
  2048;
97
#endif
98
99
#ifndef PROTECT_HFS_DEFAULT
100
#define PROTECT_HFS_DEFAULT 0
101
#endif
102
int protect_hfs = PROTECT_HFS_DEFAULT;
103
104
#ifndef PROTECT_NTFS_DEFAULT
105
#define PROTECT_NTFS_DEFAULT 1
106
#endif
107
int protect_ntfs = PROTECT_NTFS_DEFAULT;
108
109
/*
110
 * The character that begins a commented line in user-editable file
111
 * that is subject to stripspace.
112
 */
113
char comment_line_char = '#';
114
int auto_comment_line_char;
115
116
/* Parallel index stat data preload? */
117
int core_preload_index = 1;
118
119
/* This is set by setup_git_dir_gently() and/or git_default_config() */
120
char *git_work_tree_cfg;
121
122
static char *git_namespace;
123
124
/*
125
 * Repository-local GIT_* environment variables; see environment.h for details.
126
 */
127
const char * const local_repo_env[] = {
128
  ALTERNATE_DB_ENVIRONMENT,
129
  CONFIG_ENVIRONMENT,
130
  CONFIG_DATA_ENVIRONMENT,
131
  CONFIG_COUNT_ENVIRONMENT,
132
  DB_ENVIRONMENT,
133
  GIT_DIR_ENVIRONMENT,
134
  GIT_WORK_TREE_ENVIRONMENT,
135
  GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,
136
  GRAFT_ENVIRONMENT,
137
  INDEX_ENVIRONMENT,
138
  NO_REPLACE_OBJECTS_ENVIRONMENT,
139
  GIT_REPLACE_REF_BASE_ENVIRONMENT,
140
  GIT_PREFIX_ENVIRONMENT,
141
  GIT_SHALLOW_FILE_ENVIRONMENT,
142
  GIT_COMMON_DIR_ENVIRONMENT,
143
  NULL
144
};
145
146
static char *expand_namespace(const char *raw_namespace)
147
11.3k
{
148
11.3k
  struct strbuf buf = STRBUF_INIT;
149
11.3k
  struct strbuf **components, **c;
150
151
11.3k
  if (!raw_namespace || !*raw_namespace)
152
11.3k
    return xstrdup("");
153
154
0
  strbuf_addstr(&buf, raw_namespace);
155
0
  components = strbuf_split(&buf, '/');
156
0
  strbuf_reset(&buf);
157
0
  for (c = components; *c; c++)
158
0
    if (strcmp((*c)->buf, "/") != 0)
159
0
      strbuf_addf(&buf, "refs/namespaces/%s", (*c)->buf);
160
0
  strbuf_list_free(components);
161
0
  if (check_refname_format(buf.buf, 0))
162
0
    die(_("bad git namespace path \"%s\""), raw_namespace);
163
0
  strbuf_addch(&buf, '/');
164
0
  return strbuf_detach(&buf, NULL);
165
0
}
166
167
const char *getenv_safe(struct strvec *argv, const char *name)
168
56.6k
{
169
56.6k
  const char *value = getenv(name);
170
171
56.6k
  if (!value)
172
56.6k
    return NULL;
173
174
0
  strvec_push(argv, value);
175
0
  return argv->v[argv->nr - 1];
176
56.6k
}
177
178
void setup_git_env(const char *git_dir)
179
11.3k
{
180
11.3k
  char *git_replace_ref_base;
181
11.3k
  const char *shallow_file;
182
11.3k
  const char *replace_ref_base;
183
11.3k
  struct set_gitdir_args args = { NULL };
184
11.3k
  struct strvec to_free = STRVEC_INIT;
185
186
11.3k
  args.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT);
187
11.3k
  args.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT);
188
11.3k
  args.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT);
189
11.3k
  args.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);
190
11.3k
  args.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT);
191
11.3k
  if (getenv(GIT_QUARANTINE_ENVIRONMENT)) {
192
0
    args.disable_ref_updates = 1;
193
0
  }
194
195
11.3k
  repo_set_gitdir(the_repository, git_dir, &args);
196
11.3k
  strvec_clear(&to_free);
197
198
11.3k
  if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
199
0
    disable_replace_refs();
200
11.3k
  replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
201
11.3k
  git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
202
11.3k
                : "refs/replace/");
203
11.3k
  update_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);
204
205
11.3k
  free(git_namespace);
206
11.3k
  git_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
207
11.3k
  shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
208
11.3k
  if (shallow_file)
209
0
    set_alternate_shallow_file(the_repository, shallow_file, 0);
210
11.3k
}
211
212
int is_bare_repository(void)
213
53.1k
{
214
  /* if core.bare is not 'false', let's see if there is a work tree */
215
53.1k
  return is_bare_repository_cfg && !get_git_work_tree();
216
53.1k
}
217
218
int have_git_dir(void)
219
10.1k
{
220
10.1k
  return startup_info->have_repository
221
10.1k
    || the_repository->gitdir;
222
10.1k
}
223
224
const char *get_git_dir(void)
225
19.7k
{
226
19.7k
  if (!the_repository->gitdir)
227
0
    BUG("git environment hasn't been setup");
228
19.7k
  return the_repository->gitdir;
229
19.7k
}
230
231
const char *get_git_common_dir(void)
232
11.3k
{
233
11.3k
  if (!the_repository->commondir)
234
0
    BUG("git environment hasn't been setup");
235
11.3k
  return the_repository->commondir;
236
11.3k
}
237
238
const char *get_git_namespace(void)
239
0
{
240
0
  if (!git_namespace)
241
0
    BUG("git environment hasn't been setup");
242
0
  return git_namespace;
243
0
}
244
245
const char *strip_namespace(const char *namespaced_ref)
246
0
{
247
0
  const char *out;
248
0
  if (skip_prefix(namespaced_ref, get_git_namespace(), &out))
249
0
    return out;
250
0
  return NULL;
251
0
}
252
253
static int git_work_tree_initialized;
254
255
/*
256
 * Note.  This works only before you used a work tree.  This was added
257
 * primarily to support git-clone to work in a new repository it just
258
 * created, and is not meant to flip between different work trees.
259
 */
260
void set_git_work_tree(const char *new_work_tree)
261
11.3k
{
262
11.3k
  if (git_work_tree_initialized) {
263
0
    struct strbuf realpath = STRBUF_INIT;
264
265
0
    strbuf_realpath(&realpath, new_work_tree, 1);
266
0
    new_work_tree = realpath.buf;
267
0
    if (strcmp(new_work_tree, the_repository->worktree))
268
0
      die("internal error: work tree has already been set\n"
269
0
          "Current worktree: %s\nNew worktree: %s",
270
0
          the_repository->worktree, new_work_tree);
271
0
    strbuf_release(&realpath);
272
0
    return;
273
0
  }
274
11.3k
  git_work_tree_initialized = 0;
275
11.3k
  repo_set_worktree(the_repository, new_work_tree);
276
11.3k
}
277
278
const char *get_git_work_tree(void)
279
12.5k
{
280
12.5k
  return the_repository->worktree;
281
12.5k
}
282
283
const char *get_object_directory(void)
284
1.22k
{
285
1.22k
  if (!the_repository->objects->odb)
286
0
    BUG("git environment hasn't been setup");
287
1.22k
  return the_repository->objects->odb->path;
288
1.22k
}
289
290
int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)
291
0
{
292
0
  int fd;
293
  /*
294
   * we let the umask do its job, don't try to be more
295
   * restrictive except to remove write permission.
296
   */
297
0
  int mode = 0444;
298
0
  git_path_buf(temp_filename, "objects/%s", pattern);
299
0
  fd = git_mkstemp_mode(temp_filename->buf, mode);
300
0
  if (0 <= fd)
301
0
    return fd;
302
303
  /* slow path */
304
  /* some mkstemp implementations erase temp_filename on failure */
305
0
  git_path_buf(temp_filename, "objects/%s", pattern);
306
0
  safe_create_leading_directories(temp_filename->buf);
307
0
  return xmkstemp_mode(temp_filename->buf, mode);
308
0
}
309
310
int odb_pack_keep(const char *name)
311
0
{
312
0
  int fd;
313
314
0
  fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
315
0
  if (0 <= fd)
316
0
    return fd;
317
318
  /* slow path */
319
0
  safe_create_leading_directories_const(name);
320
0
  return open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
321
0
}
322
323
char *get_index_file(void)
324
21.8k
{
325
21.8k
  if (!the_repository->index_file)
326
0
    BUG("git environment hasn't been setup");
327
21.8k
  return the_repository->index_file;
328
21.8k
}
329
330
char *get_graft_file(struct repository *r)
331
1.22k
{
332
1.22k
  if (!r->graft_file)
333
0
    BUG("git environment hasn't been setup");
334
1.22k
  return r->graft_file;
335
1.22k
}
336
337
static void set_git_dir_1(const char *path)
338
11.3k
{
339
11.3k
  xsetenv(GIT_DIR_ENVIRONMENT, path, 1);
340
11.3k
  setup_git_env(path);
341
11.3k
}
342
343
static void update_relative_gitdir(const char *name UNUSED,
344
           const char *old_cwd,
345
           const char *new_cwd,
346
           void *data UNUSED)
347
0
{
348
0
  char *path = reparent_relative_path(old_cwd, new_cwd, get_git_dir());
349
0
  struct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();
350
351
0
  trace_printf_key(&trace_setup_key,
352
0
       "setup: move $GIT_DIR to '%s'",
353
0
       path);
354
0
  set_git_dir_1(path);
355
0
  if (tmp_objdir)
356
0
    tmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);
357
0
  free(path);
358
0
}
359
360
void set_git_dir(const char *path, int make_realpath)
361
11.3k
{
362
11.3k
  struct strbuf realpath = STRBUF_INIT;
363
364
11.3k
  if (make_realpath) {
365
1.22k
    strbuf_realpath(&realpath, path, 1);
366
1.22k
    path = realpath.buf;
367
1.22k
  }
368
369
11.3k
  set_git_dir_1(path);
370
11.3k
  if (!is_absolute_path(path))
371
0
    chdir_notify_register(NULL, update_relative_gitdir, NULL);
372
373
11.3k
  strbuf_release(&realpath);
374
11.3k
}
375
376
const char *get_log_output_encoding(void)
377
47.1k
{
378
47.1k
  return git_log_output_encoding ? git_log_output_encoding
379
47.1k
    : get_commit_output_encoding();
380
47.1k
}
381
382
const char *get_commit_output_encoding(void)
383
47.1k
{
384
47.1k
  return git_commit_encoding ? git_commit_encoding : "UTF-8";
385
47.1k
}
386
387
static int the_shared_repository = PERM_UMASK;
388
static int need_shared_repository_from_config = 1;
389
390
void set_shared_repository(int value)
391
0
{
392
0
  the_shared_repository = value;
393
0
  need_shared_repository_from_config = 0;
394
0
}
395
396
int get_shared_repository(void)
397
108k
{
398
108k
  if (need_shared_repository_from_config) {
399
1.22k
    const char *var = "core.sharedrepository";
400
1.22k
    const char *value;
401
1.22k
    if (!git_config_get_value(var, &value))
402
0
      the_shared_repository = git_config_perm(var, value);
403
1.22k
    need_shared_repository_from_config = 0;
404
1.22k
  }
405
108k
  return the_shared_repository;
406
108k
}
407
408
void reset_shared_repository(void)
409
1.22k
{
410
1.22k
  need_shared_repository_from_config = 1;
411
1.22k
}
412
413
int use_optional_locks(void)
414
0
{
415
0
  return git_env_bool(GIT_OPTIONAL_LOCKS_ENVIRONMENT, 1);
416
0
}
417
418
int print_sha1_ellipsis(void)
419
2.22k
{
420
  /*
421
   * Determine if the calling environment contains the variable
422
   * GIT_PRINT_SHA1_ELLIPSIS set to "yes".
423
   */
424
2.22k
  static int cached_result = -1; /* unknown */
425
426
2.22k
  if (cached_result < 0) {
427
1
    const char *v = getenv("GIT_PRINT_SHA1_ELLIPSIS");
428
1
    cached_result = (v && !strcasecmp(v, "yes"));
429
1
  }
430
2.22k
  return cached_result;
431
2.22k
}