commit - e2f45bc4f455fec482b65cea685a7bc4594e157e
commit + 6fdca49ec99627a96cda79e00f938049a317e6ef
blob - f2c23d1fc73924e118d7458514af25bd5b327fb5
blob + 3499bb5c000dbc73329c7142a6422f0d4c25ce6e
--- got/got.1
+++ got/got.1
regular expression
.Ar search-pattern .
When used together with
+.Fl p ,
+then the lines in committed patches can be matched.
+When used together with
.Fl P ,
then the file paths changed by a commit can be matched as well.
Regular expression syntax is documented in
blob - 6e4ca499c4848af7cf18908b99903326a3bb66c8
blob + 07bc4bd4b8a9a8c6c3de55769ca8f2dbb3d217b6
--- got/got.c
+++ got/got.c
static const struct got_error *
diff_blobs(struct got_object_id *blob_id1, struct got_object_id *blob_id2,
const char *path, int diff_context, int ignore_whitespace,
- int force_text_diff, struct got_repository *repo)
+ int force_text_diff, struct got_repository *repo, FILE *outfile)
{
const struct got_error *err = NULL;
struct got_blob_object *blob1 = NULL, *blob2 = NULL;
while (path[0] == '/')
path++;
err = got_diff_blob(NULL, NULL, blob1, blob2, f1, f2, path, path,
- diff_context, ignore_whitespace, force_text_diff, stdout);
+ diff_context, ignore_whitespace, force_text_diff, outfile);
done:
if (blob1)
got_object_blob_close(blob1);
static const struct got_error *
diff_trees(struct got_object_id *tree_id1, struct got_object_id *tree_id2,
const char *path, int diff_context, int ignore_whitespace,
- int force_text_diff, struct got_repository *repo)
+ int force_text_diff, struct got_repository *repo, FILE *outfile)
{
const struct got_error *err = NULL;
struct got_tree_object *tree1 = NULL, *tree2 = NULL;
arg.diff_context = diff_context;
arg.ignore_whitespace = ignore_whitespace;
arg.force_text_diff = force_text_diff;
- arg.outfile = stdout;
+ arg.outfile = outfile;
arg.line_offsets = NULL;
arg.nlines = 0;
while (path[0] == '/')
static const struct got_error *
print_patch(struct got_commit_object *commit, struct got_object_id *id,
- const char *path, int diff_context, struct got_repository *repo)
+ const char *path, int diff_context, struct got_repository *repo,
+ FILE *outfile)
{
const struct got_error *err = NULL;
struct got_commit_object *pcommit = NULL;
free(obj_id2);
goto done;
}
- printf("diff %s %s\n", id_str1 ? id_str1 : "/dev/null", id_str2);
+ fprintf(outfile,
+ "diff %s %s\n", id_str1 ? id_str1 : "/dev/null", id_str2);
switch (obj_type) {
case GOT_OBJ_TYPE_BLOB:
err = diff_blobs(obj_id1, obj_id2, path, diff_context,
- 0, 0, repo);
+ 0, 0, repo, outfile);
break;
case GOT_OBJ_TYPE_TREE:
err = diff_trees(obj_id1, obj_id2, path, diff_context,
- 0, 0, repo);
+ 0, 0, repo, outfile);
break;
default:
err = got_error(GOT_ERR_OBJ_TYPE);
if (err)
goto done;
}
- printf("diff %s %s\n", id_str1 ? id_str1 : "/dev/null",
- id_str2);
+ fprintf(outfile,
+ "diff %s %s\n", id_str1 ? id_str1 : "/dev/null", id_str2);
err = diff_trees(obj_id1, obj_id2, "", diff_context, 0, 0,
- repo);
+ repo, outfile);
}
done:
free(id_str1);
TAILQ_FOREACH(pe, changed_paths, entry) {
if (regexec(regex, pe->path, 1, ®match, 0) == 0) {
+ *have_match = 1;
+ break;
+ }
+ }
+}
+
+static const struct got_error *
+match_patch(int *have_match, struct got_commit_object *commit,
+ struct got_object_id *id, const char *path, int diff_context,
+ struct got_repository *repo, regex_t *regex)
+{
+ const struct got_error *err = NULL;
+ FILE *f;
+ char *line = NULL;
+ size_t linesize = 0;
+ ssize_t linelen;
+ regmatch_t regmatch;
+
+ *have_match = 0;
+
+ f = got_opentemp();
+ if (f == NULL)
+ return got_error_from_errno("got_opentemp");
+
+ err = print_patch(commit, id, path, diff_context, repo, f);
+ if (err)
+ goto done;
+
+ if (fseeko(f, 0L, SEEK_SET) == -1) {
+ err = got_error_from_errno("fseeko");
+ goto done;
+ }
+
+ while ((linelen = getline(&line, &linesize, f)) != -1) {
+ if (regexec(regex, line, 1, ®match, 0) == 0) {
*have_match = 1;
break;
}
}
+done:
+ free(line);
+ if (fclose(f) == EOF && err == NULL)
+ err = got_error_from_errno("fclose");
+ return err;
}
#define GOT_COMMIT_SEP_STR "-----------------------------------------------\n"
printf("\n");
}
if (show_patch) {
- err = print_patch(commit, id, path, diff_context, repo);
+ err = print_patch(commit, id, path, diff_context, repo, stdout);
if (err == 0)
printf("\n");
}
if (have_match == 0 && show_changed_paths)
match_changed_paths(&have_match,
&changed_paths, ®ex);
+ if (have_match == 0 && show_patch) {
+ err = match_patch(&have_match, commit, id,
+ path, diff_context, repo, ®ex);
+ if (err)
+ break;
+ }
if (have_match == 0) {
got_object_commit_close(commit);
TAILQ_FOREACH(pe, &changed_paths, entry) {