dir: allow exclusions from blob in addition to file
Refactor add_excludes() to separate the reading of the exclude file into a buffer and the parsing of the buffer into exclude_list items. Add add_excludes_from_blob_to_list() to allow an exclude file be specified with an OID without assuming a local worktree or index exists. Refactor read_skip_worktree_file_from_index() and add do_read_blob() to eliminate duplication of preliminary processing of blob contents. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Reviewed-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff Hostetler committed
Nov 21, 2017 at 20:58 UTC
578d81d0c445f714dce46d5f4e3f599ac3a94c75
2 files changed
+104
-31
dir.c
+101
-31
@@ -220,6 +220,57 @@ int within_depth(const char *name, int namelen,
220
return 1;
221
}
222
223
+/*
224
+ * Read the contents of the blob with the given OID into a buffer.
225
+ * Append a trailing LF to the end if the last line doesn't have one.
226
+ *
227
+ * Returns:
228
+ * -1 when the OID is invalid or unknown or does not refer to a blob.
229
+ * 0 when the blob is empty.
230
+ * 1 along with { data, size } of the (possibly augmented) buffer
231
+ * when successful.
232
+ *
233
+ * Optionally updates the given sha1_stat with the given OID (when valid).
234
+ */
235
+static int do_read_blob(const struct object_id *oid,
236
+ struct sha1_stat *sha1_stat,
237
+ size_t *size_out,
238
+ char **data_out)
239
+{
240
+ enum object_type type;
241
+ unsigned long sz;
242
+ char *data;
243
+
244
+ *size_out = 0;
245
+ *data_out = NULL;
246
+
247
+ data = read_sha1_file(oid->hash, &type, &sz);
248
+ if (!data || type != OBJ_BLOB) {
249
+ free(data);
250
+ return -1;
251
+ }
252
+
253
+ if (sha1_stat) {
254
+ memset(&sha1_stat->stat, 0, sizeof(sha1_stat->stat));
255
+ hashcpy(sha1_stat->sha1, oid->hash);
256
+ }
257
+
258
+ if (sz == 0) {
259
+ free(data);
260
+ return 0;
261
+ }
262
+
263
+ if (data[sz - 1] != '\n') {
264
+ data = xrealloc(data, st_add(sz, 1));
265
+ data[sz++] = '\n';
266
+ }
267
+
268
+ *size_out = xsize_t(sz);
269
+ *data_out = data;
270
+
271
+ return 1;
272
+}
273
+
274
#define DO_MATCH_EXCLUDE (1<<0)
275
#define DO_MATCH_DIRECTORY (1<<1)
276
#define DO_MATCH_SUBMODULE (1<<2)
@@ -600,32 +651,22 @@ void add_exclude(const char *string, const char *base,
651
x->el = el;
652
}
653
603
-static void *read_skip_worktree_file_from_index(const struct index_state *istate,
604
- const char *path, size_t *size,
605
- struct sha1_stat *sha1_stat)
654
+static int read_skip_worktree_file_from_index(const struct index_state *istate,
655
+ const char *path,
656
+ size_t *size_out,
657
+ char **data_out,
658
+ struct sha1_stat *sha1_stat)
659
{
660
int pos, len;
608
- unsigned long sz;
609
- enum object_type type;
610
- void *data;
661
662
len = strlen(path);
663
pos = index_name_pos(istate, path, len);
664
if (pos < 0)
615
- return NULL;
665
+ return -1;
666
if (!ce_skip_worktree(istate->cache[pos]))
617
- return NULL;
618
- data = read_sha1_file(istate->cache[pos]->oid.hash, &type, &sz);
619
- if (!data || type != OBJ_BLOB) {
620
- free(data);
621
- return NULL;
622
- }
623
- *size = xsize_t(sz);
624
- if (sha1_stat) {
625
- memset(&sha1_stat->stat, 0, sizeof(sha1_stat->stat));
626
- hashcpy(sha1_stat->sha1, istate->cache[pos]->oid.hash);
627
- }
628
- return data;
667
+ return -1;
668
+
669
+ return do_read_blob(&istate->cache[pos]->oid, sha1_stat, size_out, data_out);
670
}
671
672
/*
@@ -739,6 +780,10 @@ static void invalidate_directory(struct untracked_cache *uc,
780
dir->dirs[i]->recurse = 0;
781
}
782
783
+static int add_excludes_from_buffer(char *buf, size_t size,
784
+ const char *base, int baselen,
785
+ struct exclude_list *el);
786
+
787
/*
788
* Given a file with name "fname", read it (either from disk, or from
789
* an index if 'istate' is non-null), parse it and store the
@@ -754,9 +799,10 @@ static int add_excludes(const char *fname, const char *base, int baselen,
799
struct sha1_stat *sha1_stat)
800
{
801
struct stat st;
757
- int fd, i, lineno = 1;
802
+ int r;
803
+ int fd;
804
size_t size = 0;
759
- char *buf, *entry;
805
+ char *buf;
806
807
fd = open(fname, O_RDONLY);
808
if (fd < 0 || fstat(fd, &st) < 0) {
@@ -764,17 +810,13 @@ static int add_excludes(const char *fname, const char *base, int baselen,
810
warn_on_fopen_errors(fname);
811
else
812
close(fd);
767
- if (!istate ||
768
- (buf = read_skip_worktree_file_from_index(istate, fname, &size, sha1_stat)) == NULL)
813
+ if (!istate)
814
return -1;
770
- if (size == 0) {
771
- free(buf);
772
- return 0;
773
- }
774
- if (buf[size-1] != '\n') {
775
- buf = xrealloc(buf, st_add(size, 1));
776
- buf[size++] = '\n';
777
- }
815
+ r = read_skip_worktree_file_from_index(istate, fname,
816
+ &size, &buf,
817
+ sha1_stat);
818
+ if (r != 1)
819
+ return r;
820
} else {
821
size = xsize_t(st.st_size);
822
if (size == 0) {
@@ -813,6 +855,17 @@ static int add_excludes(const char *fname, const char *base, int baselen,
855
}
856
}
857
858
+ add_excludes_from_buffer(buf, size, base, baselen, el);
859
+ return 0;
860
+}
861
+
862
+static int add_excludes_from_buffer(char *buf, size_t size,
863
+ const char *base, int baselen,
864
+ struct exclude_list *el)
865
+{
866
+ int i, lineno = 1;
867
+ char *entry;
868
+
869
el->filebuf = buf;
870
871
if (skip_utf8_bom(&buf, size))
@@ -841,6 +894,23 @@ int add_excludes_from_file_to_list(const char *fname, const char *base,
894
return add_excludes(fname, base, baselen, el, istate, NULL);
895
}
896
897
+int add_excludes_from_blob_to_list(
898
+ struct object_id *oid,
899
+ const char *base, int baselen,
900
+ struct exclude_list *el)
901
+{
902
+ char *buf;
903
+ size_t size;
904
+ int r;
905
+
906
+ r = do_read_blob(oid, NULL, &size, &buf);
907
+ if (r != 1)
908
+ return r;
909
+
910
+ add_excludes_from_buffer(buf, size, base, baselen, el);
911
+ return 0;
912
+}
913
+
914
struct exclude_list *add_exclude_list(struct dir_struct *dir,
915
int group_type, const char *src)
916
{
dir.h
+3
@@ -256,6 +256,9 @@ extern struct exclude_list *add_exclude_list(struct dir_struct *dir,
256
extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
257
struct exclude_list *el, struct index_state *istate);
258
extern void add_excludes_from_file(struct dir_struct *, const char *fname);
259
+extern int add_excludes_from_blob_to_list(struct object_id *oid,
260
+ const char *base, int baselen,
261
+ struct exclude_list *el);
262
extern void parse_exclude_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen);
263
extern void add_exclude(const char *string, const char *base,
264
int baselen, struct exclude_list *el, int srcpos);