6 static void check(int error
, const char *message
)
9 fprintf(stderr
, "%s (%d)\n", message
, error
);
14 static int resolve_to_tree(
15 git_repository
*repo
, const char *identifier
, git_tree
**tree
)
18 size_t len
= strlen(identifier
);
20 git_object
*obj
= NULL
;
22 /* try to resolve as OID */
23 if (git_oid_fromstrn(&oid
, identifier
, len
) == 0)
24 git_object_lookup_prefix(&obj
, repo
, &oid
, len
, GIT_OBJ_ANY
);
26 /* try to resolve as reference */
28 git_reference
*ref
, *resolved
;
29 if (git_reference_lookup(&ref
, repo
, identifier
) == 0) {
30 git_reference_resolve(&resolved
, ref
);
31 git_reference_free(ref
);
33 git_object_lookup(&obj
, repo
, git_reference_target(resolved
), GIT_OBJ_ANY
);
34 git_reference_free(resolved
);
42 switch (git_object_type(obj
)) {
44 *tree
= (git_tree
*)obj
;
47 err
= git_commit_tree(tree
, (git_commit
*)obj
);
61 "\033[32m", /* green */
66 const git_diff_delta
*delta
,
67 const git_diff_range
*range
,
73 int *last_color
= data
, color
= 0;
75 (void)delta
; (void)range
; (void)line_len
;
77 if (*last_color
>= 0) {
79 case GIT_DIFF_LINE_ADDITION
: color
= 3; break;
80 case GIT_DIFF_LINE_DELETION
: color
= 2; break;
81 case GIT_DIFF_LINE_ADD_EOFNL
: color
= 3; break;
82 case GIT_DIFF_LINE_DEL_EOFNL
: color
= 2; break;
83 case GIT_DIFF_LINE_FILE_HDR
: color
= 1; break;
84 case GIT_DIFF_LINE_HUNK_HDR
: color
= 4; break;
87 if (color
!= *last_color
) {
88 if (*last_color
== 1 || color
== 1)
89 fputs(colors
[0], stdout
);
90 fputs(colors
[color
], stdout
);
99 static int check_uint16_param(const char *arg
, const char *pattern
, uint16_t *val
)
101 size_t len
= strlen(pattern
);
104 if (strncmp(arg
, pattern
, len
))
106 strval
= strtoul(arg
+ len
, &endptr
, 0);
113 static int check_str_param(const char *arg
, const char *pattern
, const char **val
)
115 size_t len
= strlen(pattern
);
116 if (strncmp(arg
, pattern
, len
))
118 *val
= (const char *)(arg
+ len
);
122 static void usage(const char *message
, const char *arg
)
125 fprintf(stderr
, "%s: %s\n", message
, arg
);
127 fprintf(stderr
, "%s\n", message
);
128 fprintf(stderr
, "usage: diff [<tree-oid> [<tree-oid>]]\n");
132 int main(int argc
, char *argv
[])
134 git_repository
*repo
= NULL
;
135 git_tree
*t1
= NULL
, *t2
= NULL
;
136 git_diff_options opts
= GIT_DIFF_OPTIONS_INIT
;
138 int i
, color
= -1, compact
= 0, cached
= 0;
139 char *a
, *dir
= ".", *treeish1
= NULL
, *treeish2
= NULL
;
141 memset(&opts
, 0, sizeof(opts
));
143 /* parse arguments as copied from git-diff */
145 for (i
= 1; i
< argc
; ++i
) {
149 if (treeish1
== NULL
)
151 else if (treeish2
== NULL
)
154 usage("Only one or two tree identifiers can be provided", NULL
);
156 else if (!strcmp(a
, "-p") || !strcmp(a
, "-u") ||
157 !strcmp(a
, "--patch"))
159 else if (!strcmp(a
, "--cached"))
161 else if (!strcmp(a
, "--name-status"))
163 else if (!strcmp(a
, "--color"))
165 else if (!strcmp(a
, "--no-color"))
167 else if (!strcmp(a
, "-R"))
168 opts
.flags
|= GIT_DIFF_REVERSE
;
169 else if (!strcmp(a
, "-a") || !strcmp(a
, "--text"))
170 opts
.flags
|= GIT_DIFF_FORCE_TEXT
;
171 else if (!strcmp(a
, "--ignore-space-at-eol"))
172 opts
.flags
|= GIT_DIFF_IGNORE_WHITESPACE_EOL
;
173 else if (!strcmp(a
, "-b") || !strcmp(a
, "--ignore-space-change"))
174 opts
.flags
|= GIT_DIFF_IGNORE_WHITESPACE_CHANGE
;
175 else if (!strcmp(a
, "-w") || !strcmp(a
, "--ignore-all-space"))
176 opts
.flags
|= GIT_DIFF_IGNORE_WHITESPACE
;
177 else if (!strcmp(a
, "--ignored"))
178 opts
.flags
|= GIT_DIFF_INCLUDE_IGNORED
;
179 else if (!strcmp(a
, "--untracked"))
180 opts
.flags
|= GIT_DIFF_INCLUDE_UNTRACKED
;
181 else if (!check_uint16_param(a
, "-U", &opts
.context_lines
) &&
182 !check_uint16_param(a
, "--unified=", &opts
.context_lines
) &&
183 !check_uint16_param(a
, "--inter-hunk-context=",
184 &opts
.interhunk_lines
) &&
185 !check_str_param(a
, "--src-prefix=", &opts
.old_prefix
) &&
186 !check_str_param(a
, "--dst-prefix=", &opts
.new_prefix
))
187 usage("Unknown arg", a
);
192 check(git_repository_open_ext(&repo
, dir
, 0, NULL
),
193 "Could not open repository");
196 check(resolve_to_tree(repo
, treeish1
, &t1
), "Looking up first tree");
198 check(resolve_to_tree(repo
, treeish2
, &t2
), "Looking up second tree");
201 /* <sha1> --cached */
207 check(git_diff_tree_to_tree(&diff
, repo
, t1
, t2
, &opts
), "Diff");
208 else if (t1
&& cached
)
209 check(git_diff_tree_to_index(&diff
, repo
, t1
, NULL
, &opts
), "Diff");
211 git_diff_list
*diff2
;
212 check(git_diff_tree_to_index(&diff
, repo
, t1
, NULL
, &opts
), "Diff");
213 check(git_diff_index_to_workdir(&diff2
, repo
, NULL
, &opts
), "Diff");
214 check(git_diff_merge(diff
, diff2
), "Merge diffs");
215 git_diff_list_free(diff2
);
218 check(resolve_to_tree(repo
, "HEAD", &t1
), "looking up HEAD");
219 check(git_diff_tree_to_index(&diff
, repo
, t1
, NULL
, &opts
), "Diff");
222 check(git_diff_index_to_workdir(&diff
, repo
, NULL
, &opts
), "Diff");
225 fputs(colors
[0], stdout
);
228 check(git_diff_print_compact(diff
, printer
, &color
), "Displaying diff");
230 check(git_diff_print_patch(diff
, printer
, &color
), "Displaying diff");
233 fputs(colors
[0], stdout
);
235 git_diff_list_free(diff
);
238 git_repository_free(repo
);