Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cf300bb

Browse files
committed
Initial implementation of status example
1 parent 852ded9 commit cf300bb

File tree

2 files changed

+295
-1
lines changed

2 files changed

+295
-1
lines changed

examples/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
CC = gcc
44
CFLAGS = -g -I../include -I../src -Wall -Wextra -Wmissing-prototypes -Wno-missing-field-initializers
55
LFLAGS = -L../build -lgit2 -lz
6-
APPS = general showindex diff rev-list cat-file
6+
APPS = general showindex diff rev-list cat-file status
77

88
all: $(APPS)
99

examples/status.c

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
/*
2+
* Copyright (C) 2011-2012 the libgit2 contributors
3+
*
4+
* This file is part of libgit2, distributed under the GNU GPL v2 with
5+
* a Linking Exception. For full terms see the included COPYING file.
6+
*/
7+
8+
#include <git2.h>
9+
#include <stdio.h>
10+
#include <stdlib.h>
11+
#include <string.h>
12+
13+
enum {
14+
FORMAT_DEFAULT = 0,
15+
FORMAT_LONG = 1,
16+
FORMAT_SHORT = 2,
17+
FORMAT_PORCELAIN = 3,
18+
};
19+
#define MAX_PATHSPEC 8
20+
21+
/*
22+
* This example demonstrates the use of `git_status_foreach()` to roughly
23+
* simulate the output of running `git status`. It should serve as a simple
24+
* example of how to get basic status information.
25+
*
26+
* This does not have:
27+
* - Robust error handling
28+
* - Any real command line parsing
29+
* - Colorized or paginated output formatting
30+
*
31+
*/
32+
33+
static void check(int error, const char *message, const char *extra)
34+
{
35+
const git_error *lg2err;
36+
const char *lg2msg = "", *lg2spacer = "";
37+
38+
if (!error)
39+
return;
40+
41+
if ((lg2err = giterr_last()) != NULL && lg2err->message != NULL) {
42+
lg2msg = lg2err->message;
43+
lg2spacer = " - ";
44+
}
45+
46+
if (extra)
47+
fprintf(stderr, "%s '%s' [%d]%s%s\n",
48+
message, extra, error, lg2spacer, lg2msg);
49+
else
50+
fprintf(stderr, "%s [%d]%s%s\n",
51+
message, error, lg2spacer, lg2msg);
52+
53+
exit(1);
54+
}
55+
56+
static void fail(const char *message)
57+
{
58+
check(-1, message, NULL);
59+
}
60+
61+
static void show_branch(git_repository *repo, int format)
62+
{
63+
int error = 0;
64+
const char *branch = NULL;
65+
git_reference *head = NULL;
66+
67+
error = git_repository_head(&head, repo);
68+
69+
if (error == GIT_EORPHANEDHEAD || error == GIT_ENOTFOUND)
70+
branch = NULL;
71+
else if (!error) {
72+
branch = git_reference_name(head);
73+
if (!strncmp(branch, "refs/heads/", strlen("refs/heads/")))
74+
branch += strlen("refs/heads/");
75+
} else
76+
check(error, "failed to get current branch", NULL);
77+
78+
if (format == FORMAT_LONG)
79+
printf("# %s\n", branch ? branch : "Not currently on any branch.");
80+
else
81+
printf("## %s\n", branch ? branch : "HEAD (no branch)");
82+
83+
git_reference_free(head);
84+
}
85+
86+
static void print_long(git_repository *repo, git_status_list *status)
87+
{
88+
(void)repo;
89+
(void)status;
90+
}
91+
92+
static void print_short(git_repository *repo, git_status_list *status)
93+
{
94+
size_t i, maxi = git_status_list_entrycount(status);
95+
const git_status_entry *s;
96+
char istatus, wstatus;
97+
const char *extra, *a, *b, *c;
98+
99+
for (i = 0; i < maxi; ++i) {
100+
s = git_status_byindex(status, i);
101+
102+
if (s->status == GIT_STATUS_CURRENT)
103+
continue;
104+
105+
a = b = c = NULL;
106+
istatus = wstatus = ' ';
107+
extra = "";
108+
109+
if (s->status & GIT_STATUS_INDEX_NEW)
110+
istatus = 'A';
111+
if (s->status & GIT_STATUS_INDEX_MODIFIED)
112+
istatus = 'M';
113+
if (s->status & GIT_STATUS_INDEX_DELETED)
114+
istatus = 'D';
115+
if (s->status & GIT_STATUS_INDEX_RENAMED)
116+
istatus = 'R';
117+
if (s->status & GIT_STATUS_INDEX_TYPECHANGE)
118+
istatus = 'T';
119+
120+
if (s->status & GIT_STATUS_WT_NEW) {
121+
if (istatus == ' ')
122+
istatus = '?';
123+
wstatus = '?';
124+
}
125+
if (s->status & GIT_STATUS_WT_MODIFIED)
126+
wstatus = 'M';
127+
if (s->status & GIT_STATUS_WT_DELETED)
128+
wstatus = 'D';
129+
if (s->status & GIT_STATUS_WT_RENAMED)
130+
wstatus = 'R';
131+
if (s->status & GIT_STATUS_WT_TYPECHANGE)
132+
wstatus = 'T';
133+
134+
if (s->status & GIT_STATUS_IGNORED) {
135+
istatus = '!';
136+
wstatus = '!';
137+
}
138+
139+
if (istatus == '?' && wstatus == '?')
140+
continue;
141+
142+
if (s->index_to_workdir &&
143+
s->index_to_workdir->new_file.mode == GIT_FILEMODE_COMMIT)
144+
{
145+
git_submodule *sm = NULL;
146+
unsigned int smstatus = 0;
147+
148+
if (!git_submodule_lookup(
149+
&sm, repo, s->index_to_workdir->new_file.path) &&
150+
!git_submodule_status(&smstatus, sm))
151+
{
152+
if (smstatus & GIT_SUBMODULE_STATUS_WD_MODIFIED)
153+
extra = " (new commits)";
154+
else if (smstatus & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED)
155+
extra = " (modified content)";
156+
else if (smstatus & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED)
157+
extra = " (modified content)";
158+
else if (smstatus & GIT_SUBMODULE_STATUS_WD_UNTRACKED)
159+
extra = " (untracked content)";
160+
}
161+
}
162+
163+
if (s->head_to_index) {
164+
a = s->head_to_index->old_file.path;
165+
b = s->head_to_index->new_file.path;
166+
}
167+
if (s->index_to_workdir) {
168+
if (!a)
169+
a = s->index_to_workdir->old_file.path;
170+
if (!b)
171+
b = s->index_to_workdir->old_file.path;
172+
c = s->index_to_workdir->new_file.path;
173+
}
174+
175+
if (istatus == 'R') {
176+
if (wstatus == 'R')
177+
printf("%c%c %s %s %s%s\n", istatus, wstatus, a, b, c, extra);
178+
else
179+
printf("%c%c %s %s%s\n", istatus, wstatus, a, b, extra);
180+
} else {
181+
if (wstatus == 'R')
182+
printf("%c%c %s %s%s\n", istatus, wstatus, a, c, extra);
183+
else
184+
printf("%c%c %s%s\n", istatus, wstatus, a, extra);
185+
}
186+
}
187+
188+
for (i = 0; i < maxi; ++i) {
189+
s = git_status_byindex(status, i);
190+
191+
if (s->status == GIT_STATUS_WT_NEW)
192+
printf("?? %s\n", s->index_to_workdir->old_file.path);
193+
}
194+
}
195+
196+
int main(int argc, char *argv[])
197+
{
198+
git_repository *repo = NULL;
199+
int i, npaths = 0, format = FORMAT_DEFAULT, zterm = 0, showbranch = 0;
200+
git_status_options opt = GIT_STATUS_OPTIONS_INIT;
201+
git_status_list *status;
202+
char *repodir = ".", *pathspec[MAX_PATHSPEC];
203+
204+
opt.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
205+
opt.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
206+
GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX;
207+
208+
for (i = 1; i < argc; ++i) {
209+
if (argv[i][0] != '-') {
210+
if (npaths < MAX_PATHSPEC)
211+
pathspec[npaths++] = argv[i];
212+
else
213+
fail("Example only supports a limited pathspec");
214+
}
215+
else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--short"))
216+
format = FORMAT_SHORT;
217+
else if (!strcmp(argv[i], "--long"))
218+
format = FORMAT_LONG;
219+
else if (!strcmp(argv[i], "--porcelain"))
220+
format = FORMAT_PORCELAIN;
221+
else if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--branch"))
222+
showbranch = 1;
223+
else if (!strcmp(argv[i], "-z")) {
224+
zterm = 1;
225+
if (format == FORMAT_DEFAULT)
226+
format = FORMAT_PORCELAIN;
227+
}
228+
else if (!strcmp(argv[i], "--ignored"))
229+
opt.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED;
230+
else if (!strcmp(argv[i], "-uno") ||
231+
!strcmp(argv[i], "--untracked-files=no"))
232+
opt.flags &= ~GIT_STATUS_OPT_INCLUDE_UNTRACKED;
233+
else if (!strcmp(argv[i], "-unormal") ||
234+
!strcmp(argv[i], "--untracked-files=normal"))
235+
opt.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED;
236+
else if (!strcmp(argv[i], "-uall") ||
237+
!strcmp(argv[i], "--untracked-files=all"))
238+
opt.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED |
239+
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
240+
else if (!strcmp(argv[i], "--ignore-submodules=all"))
241+
opt.flags |= GIT_STATUS_OPT_EXCLUDE_SUBMODULES;
242+
else if (!strncmp(argv[i], "--git-dir=", strlen("--git-dir=")))
243+
repodir = argv[i] + strlen("--git-dir=");
244+
else
245+
check(-1, "Unsupported option", argv[i]);
246+
}
247+
248+
if (format == FORMAT_DEFAULT)
249+
format = FORMAT_LONG;
250+
if (format == FORMAT_LONG)
251+
showbranch = 1;
252+
if (npaths > 0) {
253+
opt.pathspec.strings = pathspec;
254+
opt.pathspec.count = npaths;
255+
}
256+
257+
/*
258+
* Try to open the repository at the given path (or at the current
259+
* directory if none was given).
260+
*/
261+
check(git_repository_open_ext(&repo, repodir, 0, NULL),
262+
"Could not open repository", repodir);
263+
264+
if (git_repository_is_bare(repo))
265+
fail("Cannot report status on bare repository");
266+
267+
/*
268+
* Run status on the repository
269+
*
270+
* Because we want to simluate a full "git status" run and want to
271+
* support some command line options, we use `git_status_foreach_ext()`
272+
* instead of just the plain status call. This allows (a) iterating
273+
* over the index and then the workdir and (b) extra flags that control
274+
* which files are included. If you just want simple status (e.g. to
275+
* enumerate files that are modified) then you probably don't need the
276+
* extended API.
277+
*/
278+
check(git_status_list_new(&status, repo, &opt),
279+
"Could not get status", NULL);
280+
281+
if (showbranch)
282+
show_branch(repo, format);
283+
284+
if (format == FORMAT_LONG)
285+
print_long(repo, status);
286+
else
287+
print_short(repo, status);
288+
289+
git_status_list_free(status);
290+
git_repository_free(repo);
291+
292+
return 0;
293+
}
294+

0 commit comments

Comments
 (0)