object-file: split up concerns of `HASH_*` flags
The functions `hash_object_file()`, `write_object_file()` and `index_fd()` reuse the same set of flags to alter their behaviour. This not only adds confusion, but given that every function only supports a subset of the flags it becomes very hard to see which flags can be passed to what function. Last but not least, this entangles the implementation of all three function families. Split up concerns by creating separate flags for each of the function families. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Apr 15, 2025 at 11:38 UTC
70c0f9db4e00586e4df5cca24fe7ce05848ee59c
9 files changed
+56
-28
builtin/hash-object.c
+17
-6
@@ -19,6 +19,11 @@
19
#include "strbuf.h"
20
#include "write-or-die.h"
21
22
+enum {
23
+ HASH_OBJECT_CHECK = (1 << 0),
24
+ HASH_OBJECT_WRITE = (1 << 1),
25
+};
26
+
27
/*
28
* This is to create corrupt objects for debugging and as such it
29
* needs to bypass the data conversion performed by, and the type
@@ -33,7 +38,7 @@ static int hash_literally(struct object_id *oid, int fd, const char *type, unsig
38
ret = -1;
39
else
40
ret = write_object_file_literally(buf.buf, buf.len, type, oid,
36
- flags);
41
+ (flags & HASH_OBJECT_WRITE) ? WRITE_OBJECT_FILE_PERSIST : 0);
42
close(fd);
43
strbuf_release(&buf);
44
return ret;
@@ -42,15 +47,21 @@ static int hash_literally(struct object_id *oid, int fd, const char *type, unsig
47
static void hash_fd(int fd, const char *type, const char *path, unsigned flags,
48
int literally)
49
{
50
+ unsigned int index_flags = 0;
51
struct stat st;
52
struct object_id oid;
53
54
+ if (flags & HASH_OBJECT_WRITE)
55
+ index_flags |= INDEX_WRITE_OBJECT;
56
+ if (flags & HASH_OBJECT_CHECK)
57
+ index_flags |= INDEX_FORMAT_CHECK;
58
+
59
if (fstat(fd, &st) < 0 ||
60
(literally
61
? hash_literally(&oid, fd, type, flags)
62
: index_fd(the_repository->index, &oid, fd, &st,
52
- type_from_string(type), path, flags)))
53
- die((flags & HASH_WRITE_OBJECT)
63
+ type_from_string(type), path, index_flags)))
64
+ die((flags & HASH_OBJECT_WRITE)
65
? "Unable to add %s to database"
66
: "Unable to hash %s", path);
67
printf("%s\n", oid_to_hex(&oid));
@@ -102,13 +113,13 @@ int cmd_hash_object(int argc,
113
int no_filters = 0;
114
int literally = 0;
115
int nongit = 0;
105
- unsigned flags = HASH_FORMAT_CHECK;
116
+ unsigned flags = HASH_OBJECT_CHECK;
117
const char *vpath = NULL;
118
char *vpath_free = NULL;
119
const struct option hash_object_options[] = {
120
OPT_STRING('t', NULL, &type, N_("type"), N_("object type")),
121
OPT_BIT('w', NULL, &flags, N_("write the object into the object database"),
111
- HASH_WRITE_OBJECT),
122
+ HASH_OBJECT_WRITE),
123
OPT_COUNTUP( 0 , "stdin", &hashstdin, N_("read the object from stdin")),
124
OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")),
125
OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")),
@@ -122,7 +133,7 @@ int cmd_hash_object(int argc,
133
argc = parse_options(argc, argv, prefix, hash_object_options,
134
hash_object_usage, 0);
135
125
- if (flags & HASH_WRITE_OBJECT)
136
+ if (flags & HASH_OBJECT_WRITE)
137
prefix = setup_git_directory();
138
else
139
prefix = setup_git_directory_gently(&nongit);
builtin/replace.c
+1
-1
@@ -305,7 +305,7 @@ static int import_object(struct object_id *oid, enum object_type type,
305
strbuf_release(&result);
306
} else {
307
struct stat st;
308
- int flags = HASH_FORMAT_CHECK | HASH_WRITE_OBJECT;
308
+ int flags = INDEX_FORMAT_CHECK | INDEX_WRITE_OBJECT;
309
310
if (fstat(fd, &st) < 0) {
311
error_errno(_("unable to fstat %s"), filename);
builtin/update-index.c
+1
-1
@@ -304,7 +304,7 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len
304
ce->ce_mode = ce_mode_from_stat(old, st->st_mode);
305
306
if (index_path(the_repository->index, &ce->oid, path, st,
307
- info_only ? 0 : HASH_WRITE_OBJECT)) {
307
+ info_only ? 0 : INDEX_WRITE_OBJECT)) {
308
discard_cache_entry(ce);
309
return -1;
310
}
bulk-checkin.c
+3
-3
@@ -171,7 +171,7 @@ static int stream_blob_to_pack(struct bulk_checkin_packfile *state,
171
unsigned char obuf[16384];
172
unsigned hdrlen;
173
int status = Z_OK;
174
- int write_object = (flags & HASH_WRITE_OBJECT);
174
+ int write_object = (flags & INDEX_WRITE_OBJECT);
175
off_t offset = 0;
176
177
git_deflate_init(&s, pack_compression_level);
@@ -241,7 +241,7 @@ static int stream_blob_to_pack(struct bulk_checkin_packfile *state,
241
static void prepare_to_stream(struct bulk_checkin_packfile *state,
242
unsigned flags)
243
{
244
- if (!(flags & HASH_WRITE_OBJECT) || state->f)
244
+ if (!(flags & INDEX_WRITE_OBJECT) || state->f)
245
return;
246
247
state->f = create_tmp_packfile(the_repository, &state->pack_tmp_name);
@@ -275,7 +275,7 @@ static int deflate_blob_to_pack(struct bulk_checkin_packfile *state,
275
git_hash_update(&ctx, obuf, header_len);
276
277
/* Note: idx is non-NULL when we are writing */
278
- if ((flags & HASH_WRITE_OBJECT) != 0) {
278
+ if ((flags & INDEX_WRITE_OBJECT) != 0) {
279
CALLOC_ARRAY(idx, 1);
280
281
prepare_to_stream(state, flags);
cache-tree.c
+1
-1
@@ -452,7 +452,7 @@ static int update_one(struct cache_tree *it,
452
OBJ_TREE, &it->oid);
453
} else if (write_object_file_flags(buffer.buf, buffer.len, OBJ_TREE,
454
&it->oid, NULL, flags & WRITE_TREE_SILENT
455
- ? HASH_SILENT : 0)) {
455
+ ? WRITE_OBJECT_FILE_SILENT : 0)) {
456
strbuf_release(&buffer);
457
return -1;
458
}
notes-merge.c
+1
-1
@@ -729,7 +729,7 @@ int notes_merge_commit(struct notes_merge_options *o,
729
/* write file as blob, and add to partial_tree */
730
if (stat(path.buf, &st))
731
die_errno("Failed to stat '%s'", path.buf);
732
- if (index_path(o->repo->index, &blob_oid, path.buf, &st, HASH_WRITE_OBJECT))
732
+ if (index_path(o->repo->index, &blob_oid, path.buf, &st, INDEX_WRITE_OBJECT))
733
die("Failed to write blob object from '%s'", path.buf);
734
if (add_note(partial_tree, &obj_oid, &blob_oid, NULL))
735
die("Failed to add resolved note '%s' to notes tree",
object-file.c
+9
-9
@@ -33,9 +33,9 @@
33
34
static int get_conv_flags(unsigned flags)
35
{
36
- if (flags & HASH_RENORMALIZE)
36
+ if (flags & INDEX_RENORMALIZE)
37
return CONV_EOL_RENORMALIZE;
38
- else if (flags & HASH_WRITE_OBJECT)
38
+ else if (flags & INDEX_WRITE_OBJECT)
39
return global_conv_flags_eol | CONV_WRITE_OBJECT;
40
else
41
return 0;
@@ -835,7 +835,7 @@ static int start_loose_object_common(struct strbuf *tmp_file,
835
836
fd = create_tmpfile(tmp_file, filename);
837
if (fd < 0) {
838
- if (flags & HASH_SILENT)
838
+ if (flags & WRITE_OBJECT_FILE_SILENT)
839
return -1;
840
else if (errno == EACCES)
841
return error(_("insufficient permission for adding "
@@ -967,7 +967,7 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
967
utb.actime = mtime;
968
utb.modtime = mtime;
969
if (utime(tmp_file.buf, &utb) < 0 &&
970
- !(flags & HASH_SILENT))
970
+ !(flags & WRITE_OBJECT_FILE_SILENT))
971
warning_errno(_("failed utime() on %s"), tmp_file.buf);
972
}
973
@@ -1179,7 +1179,7 @@ int write_object_file_literally(const void *buf, unsigned long len,
1179
write_object_file_prepare_literally(the_hash_algo, buf, len, type,
1180
oid, header, &hdrlen);
1181
1182
- if (!(flags & HASH_WRITE_OBJECT))
1182
+ if (!(flags & WRITE_OBJECT_FILE_PERSIST))
1183
goto cleanup;
1184
if (freshen_packed_object(oid) || freshen_loose_object(oid))
1185
goto cleanup;
@@ -1250,7 +1250,7 @@ static int index_mem(struct index_state *istate,
1250
{
1251
struct strbuf nbuf = STRBUF_INIT;
1252
int ret = 0;
1253
- int write_object = flags & HASH_WRITE_OBJECT;
1253
+ int write_object = flags & INDEX_WRITE_OBJECT;
1254
1255
if (!type)
1256
type = OBJ_BLOB;
@@ -1265,7 +1265,7 @@ static int index_mem(struct index_state *istate,
1265
size = nbuf.len;
1266
}
1267
}
1268
- if (flags & HASH_FORMAT_CHECK) {
1268
+ if (flags & INDEX_FORMAT_CHECK) {
1269
struct fsck_options opts = FSCK_OPTIONS_DEFAULT;
1270
1271
opts.strict = 1;
@@ -1291,7 +1291,7 @@ static int index_stream_convert_blob(struct index_state *istate,
1291
unsigned flags)
1292
{
1293
int ret = 0;
1294
- const int write_object = flags & HASH_WRITE_OBJECT;
1294
+ const int write_object = flags & INDEX_WRITE_OBJECT;
1295
struct strbuf sbuf = STRBUF_INIT;
1296
1297
assert(path);
@@ -1423,7 +1423,7 @@ int index_path(struct index_state *istate, struct object_id *oid,
1423
case S_IFLNK:
1424
if (strbuf_readlink(&sb, path, st->st_size))
1425
return error_errno("readlink(\"%s\")", path);
1426
- if (!(flags & HASH_WRITE_OBJECT))
1426
+ if (!(flags & INDEX_WRITE_OBJECT))
1427
hash_object_file(the_hash_algo, sb.buf, sb.len,
1428
OBJ_BLOB, oid);
1429
else if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid))
object-file.h
+21
-4
@@ -14,10 +14,12 @@ struct index_state;
14
*/
15
extern int fetch_if_missing;
16
17
-#define HASH_WRITE_OBJECT 1
18
-#define HASH_FORMAT_CHECK 2
19
-#define HASH_RENORMALIZE 4
20
-#define HASH_SILENT 8
17
+enum {
18
+ INDEX_WRITE_OBJECT = (1 << 0),
19
+ INDEX_FORMAT_CHECK = (1 << 1),
20
+ INDEX_RENORMALIZE = (1 << 2),
21
+};
22
+
23
int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
24
int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
25
@@ -84,6 +86,21 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
86
struct object_info;
87
int parse_loose_header(const char *hdr, struct object_info *oi);
88
89
+enum {
90
+ /*
91
+ * By default, `write_object_file_literally()` does not actually write
92
+ * anything into the object store, but only computes the object ID.
93
+ * This flag changes that so that the object will be written as a loose
94
+ * object and persisted.
95
+ */
96
+ WRITE_OBJECT_FILE_PERSIST = (1 << 0),
97
+
98
+ /*
99
+ * Do not print an error in case something gose wrong.
100
+ */
101
+ WRITE_OBJECT_FILE_SILENT = (1 << 1),
102
+};
103
+
104
int write_object_file_flags(const void *buf, unsigned long len,
105
enum object_type type, struct object_id *oid,
106
struct object_id *comapt_oid_in, unsigned flags);
read-cache.c
+2
-2
@@ -706,11 +706,11 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
706
int intent_only = flags & ADD_CACHE_INTENT;
707
int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|
708
(intent_only ? ADD_CACHE_NEW_ONLY : 0));
709
- unsigned hash_flags = pretend ? 0 : HASH_WRITE_OBJECT;
709
+ unsigned hash_flags = pretend ? 0 : INDEX_WRITE_OBJECT;
710
struct object_id oid;
711
712
if (flags & ADD_CACHE_RENORMALIZE)
713
- hash_flags |= HASH_RENORMALIZE;
713
+ hash_flags |= INDEX_RENORMALIZE;
714
715
if (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))
716
return error(_("%s: can only add regular files, symbolic links or git-directories"), path);