Skip to content

Commit 70827b1

Browse files
Linus TorvaldsJunio C Hamano
authored andcommitted
Split up builtin commands into separate files from git.c
Right now it split it into "builtin-log.c" for log-related commands ("log", "show" and "whatchanged"), and "builtin-help.c" for the informational commands (usage printing and "help" and "version"). This just makes things easier to read, I find. Signed-off-by: Linus Torvalds <torvalds@osdl.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent 2857551 commit 70827b1

File tree

5 files changed

+342
-305
lines changed

5 files changed

+342
-305
lines changed

Makefile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ LIB_OBJS = \
213213
fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \
214214
$(DIFF_OBJS)
215215

216+
BUILTIN_OBJS = \
217+
builtin-log.o builtin-help.o
218+
216219
GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
217220
LIBS = $(GITLIBS) -lz
218221

@@ -462,10 +465,10 @@ all:
462465
strip: $(PROGRAMS) git$X
463466
$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
464467

465-
git$X: git.c common-cmds.h $(GITLIBS)
468+
git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS)
466469
$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
467470
$(ALL_CFLAGS) -o $@ $(filter %.c,$^) \
468-
$(ALL_LDFLAGS) $(LIBS)
471+
$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
469472

470473
$(BUILT_INS): git$X
471474
rm -f $@ && ln git$X $@
@@ -565,7 +568,7 @@ init-db.o: init-db.c
565568
$(CC) -c $(ALL_CFLAGS) \
566569
-DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c
567570

568-
$(LIB_OBJS): $(LIB_H)
571+
$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
569572
$(patsubst git-%$X,%.o,$(PROGRAMS)): $(GITLIBS)
570573
$(DIFF_OBJS): diffcore.h
571574

builtin-help.c

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
/*
2+
* builtin-help.c
3+
*
4+
* Builtin help-related commands (help, usage, version)
5+
*/
6+
#include "cache.h"
7+
#include "builtin.h"
8+
#include "exec_cmd.h"
9+
#include "common-cmds.h"
10+
11+
static const char git_usage[] =
12+
"Usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ ARGS ]";
13+
14+
/* most gui terms set COLUMNS (although some don't export it) */
15+
static int term_columns(void)
16+
{
17+
char *col_string = getenv("COLUMNS");
18+
int n_cols = 0;
19+
20+
if (col_string && (n_cols = atoi(col_string)) > 0)
21+
return n_cols;
22+
23+
#ifdef TIOCGWINSZ
24+
{
25+
struct winsize ws;
26+
if (!ioctl(1, TIOCGWINSZ, &ws)) {
27+
if (ws.ws_col)
28+
return ws.ws_col;
29+
}
30+
}
31+
#endif
32+
33+
return 80;
34+
}
35+
36+
static void oom(void)
37+
{
38+
fprintf(stderr, "git: out of memory\n");
39+
exit(1);
40+
}
41+
42+
static inline void mput_char(char c, unsigned int num)
43+
{
44+
while(num--)
45+
putchar(c);
46+
}
47+
48+
static struct cmdname {
49+
size_t len;
50+
char name[1];
51+
} **cmdname;
52+
static int cmdname_alloc, cmdname_cnt;
53+
54+
static void add_cmdname(const char *name, int len)
55+
{
56+
struct cmdname *ent;
57+
if (cmdname_alloc <= cmdname_cnt) {
58+
cmdname_alloc = cmdname_alloc + 200;
59+
cmdname = realloc(cmdname, cmdname_alloc * sizeof(*cmdname));
60+
if (!cmdname)
61+
oom();
62+
}
63+
ent = malloc(sizeof(*ent) + len);
64+
if (!ent)
65+
oom();
66+
ent->len = len;
67+
memcpy(ent->name, name, len);
68+
ent->name[len] = 0;
69+
cmdname[cmdname_cnt++] = ent;
70+
}
71+
72+
static int cmdname_compare(const void *a_, const void *b_)
73+
{
74+
struct cmdname *a = *(struct cmdname **)a_;
75+
struct cmdname *b = *(struct cmdname **)b_;
76+
return strcmp(a->name, b->name);
77+
}
78+
79+
static void pretty_print_string_list(struct cmdname **cmdname, int longest)
80+
{
81+
int cols = 1, rows;
82+
int space = longest + 1; /* min 1 SP between words */
83+
int max_cols = term_columns() - 1; /* don't print *on* the edge */
84+
int i, j;
85+
86+
if (space < max_cols)
87+
cols = max_cols / space;
88+
rows = (cmdname_cnt + cols - 1) / cols;
89+
90+
qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);
91+
92+
for (i = 0; i < rows; i++) {
93+
printf(" ");
94+
95+
for (j = 0; j < cols; j++) {
96+
int n = j * rows + i;
97+
int size = space;
98+
if (n >= cmdname_cnt)
99+
break;
100+
if (j == cols-1 || n + rows >= cmdname_cnt)
101+
size = 1;
102+
printf("%-*s", size, cmdname[n]->name);
103+
}
104+
putchar('\n');
105+
}
106+
}
107+
108+
static void list_commands(const char *exec_path, const char *pattern)
109+
{
110+
unsigned int longest = 0;
111+
char path[PATH_MAX];
112+
int dirlen;
113+
DIR *dir = opendir(exec_path);
114+
struct dirent *de;
115+
116+
if (!dir) {
117+
fprintf(stderr, "git: '%s': %s\n", exec_path, strerror(errno));
118+
exit(1);
119+
}
120+
121+
dirlen = strlen(exec_path);
122+
if (PATH_MAX - 20 < dirlen) {
123+
fprintf(stderr, "git: insanely long exec-path '%s'\n",
124+
exec_path);
125+
exit(1);
126+
}
127+
128+
memcpy(path, exec_path, dirlen);
129+
path[dirlen++] = '/';
130+
131+
while ((de = readdir(dir)) != NULL) {
132+
struct stat st;
133+
int entlen;
134+
135+
if (strncmp(de->d_name, "git-", 4))
136+
continue;
137+
strcpy(path+dirlen, de->d_name);
138+
if (stat(path, &st) || /* stat, not lstat */
139+
!S_ISREG(st.st_mode) ||
140+
!(st.st_mode & S_IXUSR))
141+
continue;
142+
143+
entlen = strlen(de->d_name);
144+
if (4 < entlen && !strcmp(de->d_name + entlen - 4, ".exe"))
145+
entlen -= 4;
146+
147+
if (longest < entlen)
148+
longest = entlen;
149+
150+
add_cmdname(de->d_name + 4, entlen-4);
151+
}
152+
closedir(dir);
153+
154+
printf("git commands available in '%s'\n", exec_path);
155+
printf("----------------------------");
156+
mput_char('-', strlen(exec_path));
157+
putchar('\n');
158+
pretty_print_string_list(cmdname, longest - 4);
159+
putchar('\n');
160+
}
161+
162+
static void list_common_cmds_help(void)
163+
{
164+
int i, longest = 0;
165+
166+
for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
167+
if (longest < strlen(common_cmds[i].name))
168+
longest = strlen(common_cmds[i].name);
169+
}
170+
171+
puts("The most commonly used git commands are:");
172+
for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
173+
printf(" %s", common_cmds[i].name);
174+
mput_char(' ', longest - strlen(common_cmds[i].name) + 4);
175+
puts(common_cmds[i].help);
176+
}
177+
puts("(use 'git help -a' to get a list of all installed git commands)");
178+
}
179+
180+
void cmd_usage(int show_all, const char *exec_path, const char *fmt, ...)
181+
{
182+
if (fmt) {
183+
va_list ap;
184+
185+
va_start(ap, fmt);
186+
printf("git: ");
187+
vprintf(fmt, ap);
188+
va_end(ap);
189+
putchar('\n');
190+
}
191+
else
192+
puts(git_usage);
193+
194+
if (exec_path) {
195+
putchar('\n');
196+
if (show_all)
197+
list_commands(exec_path, "git-*");
198+
else
199+
list_common_cmds_help();
200+
}
201+
202+
exit(1);
203+
}
204+
205+
static void show_man_page(const char *git_cmd)
206+
{
207+
const char *page;
208+
209+
if (!strncmp(git_cmd, "git", 3))
210+
page = git_cmd;
211+
else {
212+
int page_len = strlen(git_cmd) + 4;
213+
char *p = malloc(page_len + 1);
214+
strcpy(p, "git-");
215+
strcpy(p + 4, git_cmd);
216+
p[page_len] = 0;
217+
page = p;
218+
}
219+
220+
execlp("man", "man", page, NULL);
221+
}
222+
223+
int cmd_version(int argc, const char **argv, char **envp)
224+
{
225+
printf("git version %s\n", git_version_string);
226+
return 0;
227+
}
228+
229+
int cmd_help(int argc, const char **argv, char **envp)
230+
{
231+
const char *help_cmd = argv[1];
232+
if (!help_cmd)
233+
cmd_usage(0, git_exec_path(), NULL);
234+
else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a"))
235+
cmd_usage(1, git_exec_path(), NULL);
236+
else
237+
show_man_page(help_cmd);
238+
return 0;
239+
}
240+
241+

builtin-log.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Builtin "git log" and related commands (show, whatchanged)
3+
*
4+
* (C) Copyright 2006 Linus Torvalds
5+
* 2006 Junio Hamano
6+
*/
7+
#include "cache.h"
8+
#include "commit.h"
9+
#include "diff.h"
10+
#include "revision.h"
11+
#include "log-tree.h"
12+
13+
static int cmd_log_wc(int argc, const char **argv, char **envp,
14+
struct rev_info *rev)
15+
{
16+
struct commit *commit;
17+
18+
rev->abbrev = DEFAULT_ABBREV;
19+
rev->commit_format = CMIT_FMT_DEFAULT;
20+
rev->verbose_header = 1;
21+
argc = setup_revisions(argc, argv, rev, "HEAD");
22+
23+
if (argc > 1)
24+
die("unrecognized argument: %s", argv[1]);
25+
26+
prepare_revision_walk(rev);
27+
setup_pager();
28+
while ((commit = get_revision(rev)) != NULL) {
29+
log_tree_commit(rev, commit);
30+
free(commit->buffer);
31+
commit->buffer = NULL;
32+
}
33+
return 0;
34+
}
35+
36+
int cmd_whatchanged(int argc, const char **argv, char **envp)
37+
{
38+
struct rev_info rev;
39+
40+
init_revisions(&rev);
41+
rev.diff = 1;
42+
rev.diffopt.recursive = 1;
43+
return cmd_log_wc(argc, argv, envp, &rev);
44+
}
45+
46+
int cmd_show(int argc, const char **argv, char **envp)
47+
{
48+
struct rev_info rev;
49+
50+
init_revisions(&rev);
51+
rev.diff = 1;
52+
rev.diffopt.recursive = 1;
53+
rev.combine_merges = 1;
54+
rev.dense_combined_merges = 1;
55+
rev.always_show_header = 1;
56+
rev.ignore_merges = 0;
57+
rev.no_walk = 1;
58+
return cmd_log_wc(argc, argv, envp, &rev);
59+
}
60+
61+
int cmd_log(int argc, const char **argv, char **envp)
62+
{
63+
struct rev_info rev;
64+
65+
init_revisions(&rev);
66+
rev.always_show_header = 1;
67+
rev.diffopt.recursive = 1;
68+
return cmd_log_wc(argc, argv, envp, &rev);
69+
}

builtin.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef BUILTIN_H
2+
#define BUILTIN_H
3+
4+
#ifndef PATH_MAX
5+
# define PATH_MAX 4096
6+
#endif
7+
8+
extern const char git_version_string[];
9+
10+
void cmd_usage(int show_all, const char *exec_path, const char *fmt, ...)
11+
#ifdef __GNUC__
12+
__attribute__((__format__(__printf__, 3, 4), __noreturn__))
13+
#endif
14+
;
15+
16+
extern int cmd_help(int argc, const char **argv, char **envp);
17+
extern int cmd_version(int argc, const char **argv, char **envp);
18+
19+
extern int cmd_whatchanged(int argc, const char **argv, char **envp);
20+
extern int cmd_show(int argc, const char **argv, char **envp);
21+
extern int cmd_log(int argc, const char **argv, char **envp);
22+
23+
#endif

0 commit comments

Comments
 (0)