15 #define _RPMGIT_INTERNAL
30 #define SPEW(_t, _rc, _git) \
31 { if ((_t) || _rpmgit_debug ) \
32 fprintf(stderr, "<-- %s(%p) rc %d\n", __FUNCTION__, (_git), \
37 #if defined(WITH_LIBGIT2)
39 typedef struct key_s {
47 static const char *
tblName(uint32_t
v,
KEY * tbl,
size_t ntbl)
50 const char * n = NULL;
54 for (i = 0; i < ntbl; i++) {
61 (void)
snprintf(buf,
sizeof(buf),
"0x%x", (unsigned)v);
67 static const char *
fmtBits(uint32_t
flags,
KEY tbl[],
size_t ntbl,
char *t)
74 sprintf(t,
"0x%x", (
unsigned)flags);
77 for (i = 0; i < 32; i++) {
78 uint32_t mask = (1 <<
i);
84 name =
tblName(mask, tbl, ntbl);
89 if (pre ==
',') *te++ =
'>';
94 #define _ENTRY(_v) { GIT_IDXENTRY_##_v, #_v, }
96 static KEY IDXEflags[] = {
106 _ENTRY(NEW_SKIP_WORKTREE),
114 static size_t nIDXEflags =
sizeof(IDXEflags) /
sizeof(IDXEflags[0]);
116 static const char * fmtIDXEflags(uint32_t flags)
119 static char buf[BUFSIZ];
121 te =
stpcpy(te,
"\n\tflags: ");
122 (void)
fmtBits(flags, IDXEflags, nIDXEflags, te);
125 #define _IDXFLAGS(_idxeflags) fmtIDXEflags(_idxeflags)
127 #define _ENTRY(_v) { GIT_REF_##_v, #_v, }
129 static KEY REFflags[] = {
135 static size_t nREFflags =
sizeof(REFflags) /
sizeof(REFflags[0]);
137 static const char * fmtREFflags(uint32_t flags)
140 static char buf[BUFSIZ];
142 te =
stpcpy(te,
"\n\tflags: ");
143 (void)
fmtBits(flags, REFflags, nREFflags, te);
146 #define _REFFLAGS(_refflags) fmtREFflags(_refflags)
150 static void check(
int error,
const char *message,
const char *extra)
152 const git_error *lg2err;
153 const char *lg2msg =
"";
154 const char *lg2spacer =
"";
159 if ((lg2err = giterr_last()) != NULL && lg2err->message != NULL) {
160 lg2msg = lg2err->message;
165 fprintf(stderr,
"%s '%s' [%d]%s%s\n",
166 message, extra, error, lg2spacer, lg2msg);
168 fprintf(stderr,
"%s [%d]%s%s\n",
169 message, error, lg2spacer, lg2msg);
174 static int Xchkgit(
rpmgit git,
const char * msg,
175 int error,
int printit,
176 const char * func,
const char * fn,
unsigned ln)
182 const git_error * e = giterr_last();
183 char * message = (e ? e->message :
"");
184 int klass = (e ? e->klass : -12345);
186 func, fn, ln, msg, rc, message, klass);
191 #define chkgit(_git, _msg, _error) \
192 Xchkgit(_git, _msg, _error, _rpmgit_debug, __FUNCTION__, __FILE__, __LINE__)
194 void rpmgitPrintOid(
const char * msg,
const void * _oidp,
void * _fp)
196 FILE * fp = (_fp ? _fp : stderr);
197 const git_oid * oidp = _oidp;
200 t = git_oid_allocfmt(oidp);
201 git_oid_fmt(t, oidp);
204 if (msg) fprintf(fp,
"%s:", msg);
205 fprintf(fp,
" %s\n", t);
211 FILE * fp = (_fp ? _fp : stderr);
212 static const char _fmt[] =
"%c";
215 size_t _nb =
sizeof(_b);
216 size_t nw = strftime(_b, _nb-1, _fmt, localtime_r(&_Ctime, &tm));
218 if (msg) fprintf(fp,
"%s:", msg);
219 fprintf(fp,
" %s", _b);
222 void rpmgitPrintSig(
const char * msg,
const void * ___S,
void * _fp)
224 FILE * fp = (_fp ? _fp : stderr);
225 const git_signature * S = ___S;
227 if (msg) fprintf(fp,
"%s:", msg);
228 fprintf(fp,
" %s <%s>", S->name, S->email);
232 fprintf(fp,
" %lu", (
unsigned long)S->when.time);
233 fprintf(fp,
" %.02d%.02d", (S->when.offset/60), (S->when.offset%60));
240 FILE * fp = (FILE *) _fp;
241 git_index * I = (git_index *) ___I;
247 if (fp == NULL)
return;
249 Icnt = git_index_entrycount(I);
250 fprintf(fp,
"-------- Index(%u)\n", Icnt);
251 for (i = 0; i < Icnt; i++) {
252 const git_index_entry * E = git_index_get_byindex(I, i);
254 fprintf(fp,
"=== %s:", E->path);
258 fprintf(fp,
"\t dev: %x", (
unsigned)E->dev);
259 fprintf(fp,
"\n\t ino: %lu", (
unsigned long)E->ino);
260 fprintf(fp,
"\n\t mode: %o", (
unsigned)E->mode);
262 fprintf(fp,
"\n\t user: %s",
uidToUname((uid_t)E->uid));
263 fprintf(fp,
"\n\tgroup: %s",
gidToGname((gid_t)E->gid));
265 fprintf(fp,
"\n\t size: %lu", (
unsigned long)E->file_size);
271 fprintf(fp,
"%s", _IDXFLAGS(E->flags));
278 static const char * rpmgitOtype(git_otype otype)
281 const char * s =
"unknown";
283 case GIT_OBJ_ANY: s =
"any";
break;
284 case GIT_OBJ_BAD: s =
"bad";
break;
285 case GIT_OBJ__EXT1: s =
"EXT1";
break;
286 case GIT_OBJ_COMMIT: s =
"commit";
break;
287 case GIT_OBJ_TREE: s =
"tree";
break;
288 case GIT_OBJ_BLOB: s =
"blob";
break;
289 case GIT_OBJ_TAG: s =
"tag";
break;
290 case GIT_OBJ__EXT2: s =
"EXT2";
break;
291 case GIT_OBJ_OFS_DELTA: s =
"delta off";
break;
292 case GIT_OBJ_REF_DELTA: s =
"delta oid";
break;
300 git_tree * T = (git_tree *) ___T;
301 FILE * fp = (FILE *) _fp;
307 if (fp == NULL)
return;
312 Tcnt = git_tree_entrycount(T);
314 fprintf(fp,
" Tcnt: %u\n", Tcnt);
316 for (i = 0; i < Tcnt; i++) {
317 const git_tree_entry * E = git_tree_entry_byindex(T, i);
321 fprintf(fp,
" Eattrs: 0%o\n", git_tree_entry_filemode(E));
322 fprintf(fp,
" Ename: %s\n", git_tree_entry_name(E));
324 fprintf(fp,
" Etype: %s\n", rpmgitOtype(git_tree_entry_type(E)));
326 t = git_oid_allocfmt(git_tree_entry_id(E));
327 fprintf(fp,
"%06o %.4s %s\t%s\n",
328 git_tree_entry_filemode(E),
329 git_object_type2string(git_tree_entry_type(E)),
331 git_tree_entry_name(E));
339 FILE * fp = (FILE *) _fp;
340 git_commit * C = ___C;
346 if (fp == NULL)
return;
350 fprintf(fp,
" Cmsgenc: %s\n", git_commit_message_encoding(C));
351 fprintf(fp,
" Cmsg: %s\n", git_commit_message(C));
356 fprintf(fp,
" Ctz: %d\n", git_commit_time_offset(C));
361 Pcnt = git_commit_parentcount(C);
362 fprintf(fp,
" Pcnt: %u\n", Pcnt);
363 for (i = 0; i < Pcnt; i++) {
365 xx = chkgit(git,
"git_commit_parent",
366 git_commit_parent(&E, C, i));
367 const git_oid * Poidp = git_commit_parent_oid(E, i);
372 Pcnt = git_commit_parentcount(C);
373 for (i = 0; i < Pcnt; i++)
377 fprintf(fp,
"encoding: %s\n", git_commit_message_encoding(C));
378 fprintf(fp,
"\n%s", git_commit_message(C));
384 FILE * fp = (_fp ? _fp : stderr);
385 git_tag * tag = (git_tag *) _tag;
394 fprintf(fp,
" name: %s\n", git_tag_name(tag));
395 fprintf(fp,
" type: %s\n", git_object_type2string(git_tag_type(tag)));
398 fprintf(fp,
"\n%s", git_tag_message(tag));
401 fprintf(fp,
"type: %s\n", git_object_type2string(git_tag_target_type(tag)));
402 fprintf(fp,
"tag: %s\n", git_tag_name(tag));
405 fprintf(fp,
"\n%s", git_tag_message(tag));
412 FILE * fp = (_fp ? _fp : stderr);
413 git_reference * H = (___H ? ___H : git->H);
414 git_reference * Hresolved = NULL;
418 xx = chkgit(git,
"git_repository_head",
419 git_repository_head((git_reference **)&git->H, git->R));
425 xx = chkgit(git,
"git_reference_resolve",
426 git_reference_resolve(&Hresolved, H));
428 rpmgitPrintOid(
"------- Hpeel", git_reference_target_peel(H), fp);
430 fprintf(fp,
" Hname: %s\n", git_reference_name(H));
431 fprintf(fp,
" Hresolved: %p\n", Hresolved);
432 fprintf(fp,
" Howner: %p", git_reference_owner(H));
434 fprintf(fp,
" Hrtype: %d\n", (
int)git_reference_type(H));
436 fprintf(fp,
"%s\n", _REFFLAGS(git_reference_type(H)));
440 git_reference_free(Hresolved);
446 FILE * fp = (_fp ? _fp : stderr);
447 git_repository * R = ___R;
452 fprintf(fp,
"head_detached: %d\n", git_repository_head_detached(R));
453 fprintf(fp,
" head_unborn: %d\n", git_repository_head_unborn(R));
454 fprintf(fp,
" is_empty: %d\n", git_repository_is_empty(R));
455 fprintf(fp,
" is_bare: %d\n", git_repository_is_bare(R));
456 fn = git_repository_path(R);
457 fprintf(fp,
" path: %s\n", fn);
458 fn = git_repository_workdir(R);
459 fprintf(fp,
" workdir: %s\n", fn);
465 fprintf(fp,
" state: %d\n", git_repository_state(R));
466 fprintf(fp,
" namespace: %s\n", git_repository_get_namespace(R));
467 fprintf(fp,
" is_shallow: %d\n", git_repository_is_empty(R));
476 #if defined(WITH_LIBGIT2)
477 git_repository_init_options
opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
480 git_repository_free(git->R);
484 if (initopts == NULL) {
485 opts.flags = GIT_REPOSITORY_INIT_MKPATH;
487 opts.flags |= GIT_REPOSITORY_INIT_BARE;
488 initopts = (
void *) &opts;
492 rc = chkgit(git,
"git_repository_init_ext",
493 git_repository_init_ext((git_repository **)&git->R, git->fn,
494 (git_repository_init_options *)initopts));
508 #if defined(WITH_LIBGIT2)
511 {
const char * s = git_repository_workdir(git->R);
512 size_t ns = strlen(s);
513 if (strlen(fn) > ns && !strncmp(fn, s, ns))
518 rc = chkgit(git,
"git_index_add_bypath",
519 git_index_add_bypath(git->I, fn));
524 rc = chkgit(git,
"git_index_write",
525 git_index_write(git->I));
538 #if defined(WITH_LIBGIT2)
539 static const char _msg[] =
"WDJ commit";
540 static const char * update_ref =
"HEAD";
541 static const char * message_encoding =
"UTF-8";
542 git_commit * old_head = NULL;
544 const char * message = (msg ? msg : _msg);
545 const char * user_name =
546 (git->user_name ? git->user_name :
"Jeff Johnson");
547 const char * user_email =
548 (git->user_email ? git->user_email :
"jbj@jbj.org");
551 git_oid * Coidp = &_oidC;
552 git_signature * Cauthor = NULL;
553 git_signature * Ccmtter = NULL;
558 rc = chkgit(git,
"git_index_write_tree",
559 git_index_write_tree(&_oidT, git->I));
565 rc = chkgit(git,
"git_tree_lookup",
566 git_tree_lookup((git_tree **)&git->T, git->R, &_oidT));
573 rc = chkgit(git,
"git_revparse_single",
574 git_revparse_single((git_object**)&old_head,
575 git->R, update_ref));
580 rc = chkgit(git,
"git_signature_now",
581 git_signature_now(&Cauthor, user_name, user_email));
584 rc = chkgit(git,
"git_signature_now",
585 git_signature_now(&Ccmtter, user_name, user_email));
590 rc = chkgit(git,
"git_commit_create",
591 git_commit_create_v(Coidp, git->R, update_ref,
593 message_encoding, message,
602 rc = chkgit(git,
"git_commit_lookup",
603 git_commit_lookup((git_commit **)&git->C, git->R, Coidp));
606 git_tree_free(git->T);
609 rc = chkgit(git,
"git_commit_tree",
610 git_commit_tree((git_tree **)&git->T, git->C));
614 git_signature_free((git_signature *)Cauthor);
616 git_signature_free((git_signature *)Ccmtter);
623 #if defined(WITH_LIBGIT2)
624 static int rpmgitConfigCB(
const git_config_entry * CE,
void * _git)
627 const char * var_name = CE->name;
628 const char * value = CE->value;
631 if (!strcmp(
"core.bare", var_name)) {
632 git->core_bare = strcmp(value,
"false") ? 1 : 0;
634 if (!strcmp(
"core.repositoryformatversion", var_name)) {
635 git->core_repositoryformatversion = atol(value);
637 if (!strcmp(
"user.name", var_name)) {
638 git->user_name =
_free(git->user_name);
639 git->user_name =
xstrdup(value);
641 if (!strcmp(
"user.email", var_name)) {
642 git->user_email =
_free(git->user_email);
643 git->user_email =
xstrdup(value);
646 fprintf(git->fp,
"%s: %s\n", var_name, value);
657 #if defined(WITH_LIBGIT2)
659 rc = chkgit(git,
"git_repository_config",
660 git_repository_config((git_config **)&git->cfg, git->R));
664 rc = chkgit(git,
"git_config_foreach",
665 git_config_foreach(git->cfg, rpmgitConfigCB, git));
677 #if defined(WITH_LIBGIT2)
678 git_oid *
oid = (git_oid *) _oid;
680 git_oid_tostr(git->str,
sizeof(git->str), oid);
681 git->str[RPMGIT_OID_HEXSZ] =
'\0';
692 #if defined(WITH_LIBGIT2)
695 git_repository_free(git->R);
697 git->repodir =
_free(git->repodir);
709 #if defined(WITH_LIBGIT2)
711 if (git->R == NULL) {
713 git->repodir =
_free(git->repodir);
714 git->repodir =
Realpath(repodir, NULL);
715 }
else if (git->repodir == NULL) {
716 const char * dn = (git->fn ? git->fn :
".");
719 rc = chkgit(git,
"git_repository_open_ext",
720 git_repository_open_ext((git_repository **)&git->R, git->repodir, 0, NULL));
733 #if defined(WITH_LIBGIT2)
734 const git_tree_entry *entry;
747 #if defined(WITH_LIBGIT2)
748 FILE * fp = (git->fp ? git->fp : stdout);
753 xx = chkgit(git,
"git_revwalk_new",
754 git_revwalk_new(&walk, git->R));
755 git_revwalk_sorting(walk, GIT_SORT_TOPOLOGICAL | GIT_SORT_REVERSE);
756 xx = chkgit(git,
"git_revwalk_push_head",
757 git_revwalk_push_head(walk));
758 git->walk = (
void *) walk;
760 while ((xx = chkgit(git,
"git_revwalk_next",
761 git_revwalk_next(&oid, walk))) == GIT_OK)
764 const git_signature * S;
766 xx = chkgit(git,
"git_commit_lookup",
767 git_commit_lookup(&C, git->R, &oid));
769 S = git_commit_author(C);
770 fprintf(fp,
"Author: %s <%s>", S->name, S->email);
772 fprintf(fp,
"\n%s", git_commit_message(C));
778 git_revwalk_free(walk);
792 #if defined(WITH_LIBGIT2)
793 FILE * fp = (git->fp ? git->fp : stdout);
801 xx = chkgit(git,
"git_repository_index",
802 git_repository_index((git_index **)&git->I, git->R));
803 xx = chkgit(git,
"git_index_read",
804 git_index_read(git->I, 0));
806 ecount = git_index_entrycount(git->I);
807 for (i = 0; i < ecount; i++) {
808 static const char _fmt[] =
"%c";
809 const git_index_entry * e = git_index_get_byindex(git->I, i);
814 fprintf(fp,
"=== %s:", e->path);
816 git_oid_fmt(t, &oid);
817 t[GIT_OID_HEXSZ] =
'\0';
818 fprintf(fp,
"\n\t oid: %s", t);
820 fprintf(fp,
"\n\t dev: %x", (
unsigned)e->dev);
821 fprintf(fp,
"\n\t ino: %lu", (
unsigned long)e->ino);
822 fprintf(fp,
"\n\t mode: %o", (
unsigned)e->mode);
824 fprintf(fp,
"\n\t user: %s",
uidToUname((uid_t)e->uid));
825 fprintf(fp,
"\n\tgroup: %s",
gidToGname((gid_t)e->gid));
827 fprintf(fp,
"\n\t size: %lu", (
unsigned long)e->file_size);
829 mtime = e->ctime.seconds;
830 nb = strftime(t, nt, _fmt, localtime_r(&mtime, &tm));
831 fprintf(fp,
"\n\tctime: %s", t);
833 mtime = e->mtime.seconds;
834 nb = strftime(t, nt, _fmt, localtime_r(&mtime, &tm));
835 fprintf(fp,
"\n\tmtime: %s", t);
837 fprintf(fp,
"%s", _IDXFLAGS(e->flags));
842 git_index_free(git->I);
853 #if defined(WITH_LIBGIT2) && defined(NOTYET)
854 FILE * fp = (git->fp ? git->fp : stdout);
855 git_odb * odb = git_repository_database(git->R);
856 git_odb_object *
obj;
858 unsigned char *
data;
859 const char * str_type;
862 rc = git_odb_read(&obj, odb, &oid);
863 data = (
char *)git_odb_object_data(obj);
864 otype = git_odb_object_type(oid);
865 str_type = git_object_type2string(otype);
866 fprintf(fp,
"object length and type: %d, %s\n",
867 (
int)git_odb_object_size(obj), str_type);
869 git_odb_object_close(obj);
880 #if defined(WITH_LIBGIT2) && defined(NOTYET)
881 FILE * fp = (git->fp ? git->fp : stdout);
882 git_odb * odb = git_repository_database(git->R);
884 size_t nb = GIT_OID_HEXSZ;
887 nb = strncpy(b, nb,
"blah blah") -
b;
888 rc = git_odb_write(&oid, odb, b, nb, GIT_OBJ_BLOB);
889 git_oid_format(b, &oid);
890 fprintf(fp,
"Written Object: %s\n", b);
902 static int _popt_flags = POPT_CONTEXT_POSIXMEHARDER;
907 #if defined(WITH_LIBGIT2)
911 git->con = poptFreeContext(git->con);
912 git->con = poptGetContext(argv[0], argc, (
const char **)argv, opts, _popt_flags);
914 while ((rc = poptGetNextOpt(git->con)) > 0) {
915 const char *
arg = poptGetOptArg(git->con);
919 fprintf(stderr,
"%s: %s: %s\n", argv[0],
920 poptBadOption(git->con, POPT_BADOPTION_NOALIAS),
922 git->con = poptFreeContext(git->con);
935 #if defined(WITH_LIBGIT2)
936 static uint32_t parse_shared(
const char * shared)
938 if (!strcmp(shared,
"false")
939 || !strcmp(shared,
"umask"))
940 return GIT_REPOSITORY_INIT_SHARED_UMASK;
941 else if (!strcmp(shared,
"true")
942 || !strcmp(shared,
"group"))
943 return GIT_REPOSITORY_INIT_SHARED_GROUP;
944 else if (!strcmp(shared,
"all")
945 || !strcmp(shared,
"world")
946 || !strcmp(shared,
"everybody"))
947 return GIT_REPOSITORY_INIT_SHARED_ALL;
948 else if (shared[0] ==
'0') {
950 long val = strtol(shared + 1, &end, 8);
951 if (end == shared + 1 || *end != 0)
953 return (uint32_t)val;
966 static int create_initial_commit(
rpmgit git,
void * ___R)
968 FILE * fp = (git->fp ? git->fp : stderr);
974 xx = chkgit(git,
"git_signature_default",
975 git_signature_default((git_signature **)&git->S, git->R));
977 fprintf(fp,
"Unable to create a commit signature.\n"
978 "Perhaps 'user.name' and 'user.email' are not set\n");
983 xx = chkgit(git,
"git_repository_index",
984 git_repository_index((git_index **)&git->I, git->R));
986 fprintf(fp,
"Could not open repository index\n");
994 xx = chkgit(git,
"git_index_write_tree",
995 git_index_write_tree(&Toid, git->I));
997 fprintf(fp,
"Unable to write initial tree from index\n");
1001 git_index_free(git->I);
1004 xx = chkgit(git,
"git_tree_lookup",
1005 git_tree_lookup((git_tree **)&git->T, git->R, &Toid));
1007 fprintf(fp,
"Could not look up initial tree\n");
1017 xx = chkgit(git,
"git_commit_create_v",
1018 git_commit_create_v(&Coid, git->R,
"HEAD", git->S, git->S,
1019 NULL,
"RPM init commit", git->T, 0));
1021 fprintf(fp,
"Could not create the initial commit\n");
1029 git_signature_free(git->I);
1034 git_tree_free(git->T);
1038 git_signature_free(git->S);
1048 #if defined(WITH_LIBGIT2)
1049 const char * init_template = NULL;
1050 const char * init_shared = NULL;
1051 const char * init_gitdir = NULL;
1053 _INIT_QUIET = (1 << 0),
1054 _INIT_BARE = (1 << 1),
1055 _INIT_COMMIT = (1 << 2),
1058 #define INIT_ISSET(_a) (init_flags & _INIT_##_a)
1059 struct poptOption initOpts[] = {
1060 {
"bare",
'\0', POPT_BIT_SET, &init_flags, _INIT_BARE,
1061 N_(
"Create a bare repository."), NULL },
1062 {
"template",
'\0', POPT_ARG_STRING, &init_template, 0,
1063 N_(
"Specify the <template> directory."),
N_(
"<template>") },
1065 {
"shared",
'\0', POPT_ARG_STRING, &init_shared, 0,
1066 N_(
"Specify how the git repository is to be shared."),
1067 N_(
"{false|true|umask|group|all|world|everybody|0xxx}") },
1068 {
"separate-git-dir",
'\0', POPT_ARG_STRING, &init_gitdir, 0,
1069 N_(
"Specify a separate <gitdir> directory."),
N_(
"<gitdir>") },
1070 {
"quiet",
'q', POPT_BIT_SET, &init_flags, _INIT_QUIET,
1071 N_(
"Quiet mode."), NULL },
1072 {
"initial-commit",
'\0', POPT_BIT_SET, &init_flags, _INIT_COMMIT,
1073 N_(
"Initial commit.."), NULL },
1080 git_repository_init_options
opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
1082 const char * dir = git->fn;
1087 fprintf(stderr,
"==> %s(%p[%d]) git %p flags 0x%x\n", __FUNCTION__, argv, argc, git, init_flags);
1096 opts.flags = GIT_REPOSITORY_INIT_MKPATH;
1097 if (INIT_ISSET(BARE)) {
1099 opts.flags |= GIT_REPOSITORY_INIT_BARE;
1102 if (init_template) {
1103 opts.flags |= GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
1104 opts.template_path = init_template;
1108 opts.workdir_path = dir;
1112 git->shared_umask = parse_shared(init_shared);
1114 git->shared_umask = GIT_REPOSITORY_INIT_SHARED_UMASK;
1122 if (!INIT_ISSET(QUIET)) {
1123 if (git->is_bare || init_gitdir)
1124 dir = git_repository_path(git->R);
1126 dir = git_repository_workdir(git->R);
1127 printf(
"Initialized empty Git repository in %s\n", dir);
1141 if (INIT_ISSET(COMMIT)) {
1142 xx = create_initial_commit(git, git->R);
1145 printf(
"Created empty initial commit\n");
1154 for (i = 0; i < git->ac; i++) {
1155 const char * fn = git->av[
i];
1165 static const char _msg[] =
"WDJ commit";
1178 init_gitdir =
_free(init_gitdir);
1179 init_shared =
_free(init_shared);
1180 init_template =
_free(init_template);
1190 #if defined(WITH_LIBGIT2)
1191 static int print_matched_cb(
const char * fn,
const char *matched_pathspec,
1196 git_status_t status;
1200 (void) matched_pathspec;
1202 xx = chkgit(git,
"git_status_file",
1203 git_status_file((
unsigned int *) &status, git->R, fn));
1207 if (status & GIT_STATUS_WT_MODIFIED || status & GIT_STATUS_WT_NEW) {
1208 fprintf(fp,
"add '%s'\n", fn);
1223 Files to add content from. Fileglobs (e.g. *.c) can be given to
1224 add all matching files. Also a leading directory
name (e.g. dir to
1225 add dir/file1 and dir/file2) can be given to add all files
in the
1226 directory, recursively.
1229 Don’t actually add the
file(s), just show
if they exist.
1235 Allow adding otherwise ignored files.
1238 Add modified contents
in the working tree interactively to the
1239 index. Optional path arguments may be supplied to
limit operation
1240 to a subset of the working tree. See “Interactive mode”
for
1244 Interactively choose hunks of patch between the index and the work
1245 tree and add them to the index. This gives the
user a chance to
1246 review the difference before adding modified contents to the index.
1248 This effectively runs add --interactive, but bypasses the initial
1249 command menu and directly jumps to the patch subcommand. See
1250 “Interactive mode”
for details.
1253 Open the diff vs. the index
in an editor and let the
user edit it.
1254 After the editor was closed, adjust the hunk headers and apply the
1257 NOTE: Obviously,
if you change anything
else than the first
1258 character on lines beginning with a space or a minus, the patch
1259 will no longer apply.
1262 Only match <filepattern> against already tracked files
in the index
1263 rather than the working tree. That means that it will never stage
1264 new files, but that it will stage modified
new contents of tracked
1265 files and that it will
remove files from the index
if the
1266 corresponding files
in the working tree have been removed.
1268 If no <filepattern> is given,
default to
".";
in other words,
1269 update all tracked files
in the
current directory and its
1273 Like -u, but match <filepattern> against files
in the working tree
1274 in addition to the index. That means that it will find
new files as
1275 well as staging modified content and removing files that are no
1276 longer
in the working tree.
1279 Record only the fact that the path will be added later. An entry
1280 for the path is placed
in the index with no content. This is useful
1281 for, among other things, showing the unstaged content of such files
1282 with git diff and committing them with git commit -a.
1285 Don’t add the
file(s), but only refresh their stat() information
in
1289 If some files could not be added because of errors indexing them,
1290 do not abort the operation, but
continue adding the others. The
1294 This option can be used to separate
command-line
options from the
1295 list of files, (useful when
filenames might be mistaken
for
1303 #if defined(WITH_LIBGIT2)
1305 _ADD_SKIP = (1 << 0),
1306 _ADD_VERBOSE = (1 << 1),
1307 _ADD_FORCE = (1 << 2),
1308 _ADD_INTERACTIVE = (1 << 3),
1309 _ADD_PATCH = (1 << 4),
1310 _ADD_EDIT = (1 << 5),
1311 _ADD_UPDATE = (1 << 6),
1312 _ADD_ALL = (1 << 7),
1313 _ADD_INTENT_TO_ADD = (1 << 8),
1314 _ADD_REFRESH = (1 << 9),
1315 _ADD_IGNORE_ERRORS = (1 << 10),
1318 #define ADD_ISSET(_a) (add_flags & _ADD_##_a)
1319 struct poptOption addOpts[] = {
1320 {
"dry-run",
'n', POPT_BIT_SET, &add_flags, _ADD_SKIP,
1322 {
"verbose",
'v', POPT_BIT_SET, &add_flags, _ADD_VERBOSE,
1323 N_(
"Verbose mode."), NULL },
1324 {
"force",
'f', POPT_BIT_SET, &add_flags, _ADD_FORCE,
1326 {
"interactive",
'i', POPT_BIT_SET, &add_flags, _ADD_INTERACTIVE,
1328 {
"patch",
'p', POPT_BIT_SET, &add_flags, _ADD_PATCH,
1330 {
"edit",
'e', POPT_BIT_SET, &add_flags, _ADD_EDIT,
1332 {
"update",
'u', POPT_BIT_SET, &add_flags, _ADD_UPDATE,
1334 {
"all",
'A', POPT_BIT_SET, &add_flags, _ADD_ALL,
1336 {
"intent-to-add",
'N', POPT_BIT_SET, &add_flags, _ADD_INTENT_TO_ADD,
1338 {
"refresh",
'\0', POPT_BIT_SET, &add_flags, _ADD_REFRESH,
1340 {
"ignore-errors",
'\0', POPT_BIT_SET, &add_flags, _ADD_IGNORE_ERRORS,
1349 git_index_matched_path_cb matched_cb = NULL;
1351 git_strarray array = {0};
1352 array.strings = (
char **) git->av;
1353 array.count = git->ac;
1355 if (ADD_ISSET(VERBOSE) || ADD_ISSET(SKIP))
1356 matched_cb = print_matched_cb;
1359 xx = chkgit(git,
"git_repository_index",
1360 git_repository_index((git_index **)&git->I, git->R));
1365 if (ADD_ISSET(UPDATE))
1366 xx = chkgit(git,
"git_index_update_all",
1367 git_index_update_all(git->I, &array, matched_cb, git));
1369 xx = chkgit(git,
"git_index_add_all",
1370 git_index_add_all(git->I, &array, 0, matched_cb, git));
1373 xx = chkgit(git,
"git_index_write",
1374 git_index_write(git->I));
1381 git_index_free(git->I);
1394 #if defined(WITH_LIBGIT2)
1395 const char * commit_file = NULL;
1396 const char * commit_author = NULL;
1397 const char * commit_date = NULL;
1398 const char * commit_msg = NULL;
1399 const char * commit_template = NULL;
1400 const char * commit_cleanup = NULL;
1401 const char * commit_untracked = NULL;
1403 _COMMIT_ALL = (1 << 0),
1404 _COMMIT_RESET_AUTHOR = (1 << 1),
1405 _COMMIT_SHORT = (1 << 2),
1406 _COMMIT_PORCELAIN = (1 << 3),
1407 _COMMIT_ZERO = (1 << 4),
1408 _COMMIT_SIGNOFF = (1 << 5),
1409 _COMMIT_NO_VERIFY = (1 << 6),
1410 _COMMIT_ALLOW_EMPTY = (1 << 7),
1411 _COMMIT_EDIT = (1 << 8),
1412 _COMMIT_AMEND = (1 << 9),
1413 _COMMIT_INCLUDE = (1 << 10),
1414 _COMMIT_ONLY = (1 << 11),
1415 _COMMIT_VERBOSE = (1 << 12),
1416 _COMMIT_QUIET = (1 << 13),
1417 _COMMIT_DRY_RUN = (1 << 14),
1418 _COMMIT_STATUS = (1 << 15),
1419 _COMMIT_NO_STATUS = (1 << 16),
1421 int commit_flags = 0;
1422 #define COMMIT_ISSET(_a) (commit_flags & _COMMIT_##_a)
1423 struct poptOption commitOpts[] = {
1424 {
"all",
'a', POPT_BIT_SET, &commit_flags, _COMMIT_ALL,
1428 {
"reset-author",
'\0', POPT_BIT_SET, &commit_flags, _COMMIT_RESET_AUTHOR,
1430 {
"short",
'\0', POPT_BIT_SET, &commit_flags, _COMMIT_SHORT,
1432 {
"porcelain",
'\0', POPT_BIT_SET, &commit_flags, _COMMIT_PORCELAIN,
1434 { NULL,
'z', POPT_BIT_SET, &commit_flags, _COMMIT_ZERO,
1436 {
"file",
'F', POPT_ARG_STRING, &commit_file, 0,
1438 {
"author",
'\0', POPT_ARG_STRING, &commit_author, 0,
1440 {
"date",
'\0', POPT_ARG_STRING, &commit_date, 0,
1442 {
"message",
'm', POPT_ARG_STRING, &commit_msg, 0,
1444 {
"template",
't', POPT_ARG_STRING, &commit_template, 0,
1446 {
"signoff",
's', POPT_BIT_SET, &commit_flags, _COMMIT_SIGNOFF,
1448 {
"no-verify",
'n', POPT_BIT_SET, &commit_flags, _COMMIT_NO_VERIFY,
1450 {
"allow-empty",
'\0', POPT_BIT_SET, &commit_flags, _COMMIT_ALLOW_EMPTY,
1452 {
"cleanup",
'\0', POPT_ARG_STRING, &commit_cleanup, 0,
1454 {
"edit",
'e', POPT_BIT_SET, &commit_flags, _COMMIT_EDIT,
1456 {
"amend",
'\0', POPT_BIT_SET, &commit_flags, _COMMIT_AMEND,
1458 {
"include",
'i', POPT_BIT_SET, &commit_flags, _COMMIT_INCLUDE,
1460 {
"only",
'o', POPT_BIT_SET, &commit_flags, _COMMIT_ONLY,
1462 {
"untracked",
'u', POPT_ARG_STRING, &commit_untracked, 0,
1464 {
"verbose",
'v', POPT_BIT_SET, &commit_flags, _COMMIT_VERBOSE,
1465 N_(
"Verbose mode."), NULL },
1466 {
"quiet",
'q', POPT_BIT_SET, &commit_flags, _COMMIT_QUIET,
1467 N_(
"Quiet mode."), NULL },
1468 {
"dry-run",
'\n', POPT_BIT_SET, &commit_flags, _COMMIT_DRY_RUN,
1471 {
"status",
'\0', POPT_BIT_SET, &commit_flags, _COMMIT_STATUS,
1473 {
"no-status",
'\0', POPT_BIT_SET, &commit_flags, _COMMIT_NO_STATUS,
1484 xx = chkgit(git,
"git_repository_index",
1485 git_repository_index((git_index **)&git->I, git->R));
1490 if (commit_msg == NULL) commit_msg =
xstrdup(
"WDJ commit");
1502 commit_file =
_free(commit_file);
1503 commit_author =
_free(commit_author);
1504 commit_date =
_free(commit_date);
1505 commit_msg =
_free(commit_msg);
1506 commit_template =
_free(commit_template);
1507 commit_cleanup =
_free(commit_cleanup);
1508 commit_untracked =
_free(commit_untracked);
1518 #if defined(WITH_LIBGIT2)
1519 static int diff_output(
const git_diff_delta *
d,
const git_diff_hunk *h,
1520 const git_diff_line *l,
void *p)
1522 FILE *fp = (FILE*)p;
1530 if (l->origin == GIT_DIFF_LINE_CONTEXT ||
1531 l->origin == GIT_DIFF_LINE_ADDITION ||
1532 l->origin == GIT_DIFF_LINE_DELETION)
1533 fputc(l->origin, fp);
1535 nw = fwrite(l->content, 1, l->content_len, fp);
1540 static int treeish_to_tree(git_tree ** tree, git_repository * repo,
1541 const char * treeish)
1543 git_object *
obj = NULL;
1546 if ((err = git_revparse_single(&obj, repo, treeish)) < 0)
1549 if ((err = git_object_peel((git_object **)tree, obj, GIT_OBJ_TREE)) < 0)
1552 git_object_free(obj);
1557 static char *colors[] = {
1566 OUTPUT_DIFF = (1 << 0),
1567 OUTPUT_STAT = (1 << 1),
1568 OUTPUT_SHORTSTAT = (1 << 2),
1569 OUTPUT_NUMSTAT = (1 << 3),
1570 OUTPUT_SUMMARY = (1 << 4)
1581 git_diff_options diffopts;
1582 git_diff_find_options findopts;
1586 git_diff_format_t format;
1587 const char *treeish1;
1588 const char *treeish2;
1592 static int color_printer(
1593 const git_diff_delta *delta,
1594 const git_diff_hunk *hunk,
1595 const git_diff_line *line,
1598 int *last_color =
data;
1601 if (*last_color >= 0) {
1602 switch (line->origin) {
1603 case GIT_DIFF_LINE_ADDITION: color = 3;
break;
1604 case GIT_DIFF_LINE_DELETION: color = 2;
break;
1605 case GIT_DIFF_LINE_ADD_EOFNL: color = 3;
break;
1606 case GIT_DIFF_LINE_DEL_EOFNL: color = 2;
break;
1607 case GIT_DIFF_LINE_FILE_HDR: color = 1;
break;
1608 case GIT_DIFF_LINE_HUNK_HDR: color = 4;
break;
1611 if (color != *last_color) {
1612 if (*last_color == 1 || color == 1)
1613 fputs(colors[0], stdout);
1614 fputs(colors[color], stdout);
1615 *last_color = color;
1619 return diff_output(delta, hunk, line, stdout);
1623 static void diff_print_stats(
rpmgit git, git_diff *diff,
struct opts *o)
1625 git_diff_stats *stats;
1626 git_buf
b = GIT_BUF_INIT_CONST(NULL, 0);
1627 git_diff_stats_format_t format = 0;
1630 xx = chkgit(git,
"git_diff_get_stats",
1631 git_diff_get_stats(&stats, diff));
1633 if (o->output & OUTPUT_STAT)
1634 format |= GIT_DIFF_STATS_FULL;
1635 if (o->output & OUTPUT_SHORTSTAT)
1636 format |= GIT_DIFF_STATS_SHORT;
1637 if (o->output & OUTPUT_NUMSTAT)
1638 format |= GIT_DIFF_STATS_NUMBER;
1639 if (o->output & OUTPUT_SUMMARY)
1640 format |= GIT_DIFF_STATS_INCLUDE_SUMMARY;
1642 xx = chkgit(git,
"git_diff_stats_to_buf",
1643 git_diff_stats_to_buf(&b, stats, format, 80));
1645 fputs(b.ptr, stdout);
1648 git_diff_stats_free(stats);
1656 #if defined(WITH_LIBGIT2)
1658 GIT_DIFF_OPTIONS_INIT, GIT_DIFF_FIND_OPTIONS_INIT,
1659 -1, 0, OUTPUT_DIFF, GIT_DIFF_FORMAT_PATCH, NULL, NULL,
"."
1662 _DIFF_ALL = (1 << 0),
1663 _DIFF_ZERO = (1 << 1),
1666 #define DIFF_ISSET(_a) (o.diffopts.flags & GIT_DIFF_##_a)
1667 struct poptOption diffOpts[] = {
1669 {
"patch",
'p', POPT_ARG_VAL, &o.format, GIT_DIFF_FORMAT_PATCH,
1670 N_(
"Generate patch."), NULL },
1672 {
"cached",
'\0', POPT_ARG_VAL, &o.cache, CACHE_ONLY,
1674 {
"nocache",
'\0', POPT_ARG_VAL, &o.cache, CACHE_NONE,
1679 {
"raw",
'\0', POPT_ARG_VAL, &o.format, GIT_DIFF_FORMAT_RAW,
1683 { NULL,
'z', POPT_BIT_SET, &diff_flags, _DIFF_ZERO,
1686 {
"name-only",
'\0', POPT_ARG_VAL, &o.format, GIT_DIFF_FORMAT_NAME_ONLY,
1687 N_(
"Show only names of changed files."), NULL },
1689 {
"name-status",
'\0', POPT_ARG_VAL, &o.format, GIT_DIFF_FORMAT_NAME_STATUS,
1690 N_(
"Show only names and status of changed files."), NULL },
1693 {
"color",
'\0', POPT_ARG_VAL, &o.color, 0,
1694 N_(
"Show colored diff."), NULL },
1695 {
"no-color",
'\0', POPT_ARG_VAL, &o.color, -1,
1696 N_(
"Turn off colored diff."), NULL },
1708 { NULL,
'R', POPT_BIT_SET, &o.diffopts.flags, GIT_DIFF_REVERSE,
1709 N_(
"Swap two inputs."), NULL },
1711 {
"text",
'a', POPT_BIT_SET, &o.diffopts.flags, GIT_DIFF_FORCE_TEXT,
1712 N_(
"Treat all files as text."), NULL },
1713 {
"ignore-space-at-eol",
'\0', POPT_BIT_SET, &o.diffopts.flags, GIT_DIFF_IGNORE_WHITESPACE_EOL,
1714 N_(
"Ignore changes in whitespace at EOL."), NULL },
1715 {
"ignore-space-change",
'b', POPT_BIT_SET, &o.diffopts.flags, GIT_DIFF_IGNORE_WHITESPACE_CHANGE,
1716 N_(
"Ignore changes in amount of whitespace."), NULL },
1717 {
"ignore-all-space",
'w', POPT_BIT_SET, &o.diffopts.flags, GIT_DIFF_IGNORE_WHITESPACE,
1718 N_(
"Ignore whitespace when comparing lines."), NULL },
1719 {
"ignored",
'\0', POPT_BIT_SET, &o.diffopts.flags, GIT_DIFF_INCLUDE_IGNORED,
1721 {
"untracked",
'\0', POPT_BIT_SET, &o.diffopts.flags, GIT_DIFF_INCLUDE_UNTRACKED,
1723 {
"patience",
'\0', POPT_BIT_SET, &o.diffopts.flags, GIT_DIFF_PATIENCE,
1724 N_(
"Generate a diff using the \"patience diff\" algorithm."), NULL },
1725 {
"minimal",
'\0', POPT_BIT_SET, &o.diffopts.flags, GIT_DIFF_MINIMAL,
1726 N_(
"Generate a minimal diff."), NULL },
1728 {
"stat",
'\0', POPT_BIT_SET, &o.output, OUTPUT_STAT,
1730 {
"numstat",
'\0', POPT_BIT_SET, &o.output, OUTPUT_NUMSTAT,
1732 {
"shortstat",
'\0', POPT_BIT_SET, &o.output, OUTPUT_SHORTSTAT,
1736 {
"summary",
'\0', POPT_ARG_VAL, &o.output, OUTPUT_SUMMARY,
1739 {
"find-renames",
'M', POPT_ARG_SHORT, &o.findopts.rename_threshold, 0,
1741 {
"find-copies",
'C', POPT_ARG_SHORT, &o.findopts.copy_threshold, 0,
1743 {
"find-copies-harder",
'\0', POPT_BIT_SET, &o.findopts.flags, GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED,
1746 {
"break-rewrites",
'B', POPT_BIT_SET, &o.findopts.flags, GIT_DIFF_FIND_REWRITES,
1748 {
"unified",
'U', POPT_ARG_SHORT, &o.diffopts.context_lines, 0,
1749 N_(
"Generate diffs with <n> lines of context."),
N_(
"<n>") },
1751 {
"inter-hunk-context",
'\0', POPT_ARG_SHORT, &o.diffopts.interhunk_lines, 0,
1752 N_(
"Show the context between diff hunks."),
N_(
"<lines>") },
1754 {
"abbrev",
'\0', POPT_ARG_SHORT, &o.diffopts.interhunk_lines, 0,
1755 (
""),
N_(
"<XXX>") },
1761 {
"ignore-submodules",
'\0', POPT_BIT_SET, &o.diffopts.flags, GIT_DIFF_IGNORE_SUBMODULES,
1762 N_(
"Ignore changes to submodules in the diff generation."), NULL },
1763 {
"src-prefix",
'\0', POPT_ARG_STRING, &o.diffopts.old_prefix, 0,
1764 N_(
"Show the given source <prefix> instead of \"a/\"."),
N_(
"<prefix>") },
1765 {
"dst-prefix",
'\0', POPT_ARG_STRING, &o.diffopts.new_prefix, 0,
1766 N_(
"Show the given destination prefix instead of \"b/\"."),
N_(
"<prefix>") },
1777 git_diff * diff = NULL;
1778 const char * treeish1 = NULL;
1779 git_tree *t1 = NULL;
1780 const char * treeish2 = NULL;
1781 git_tree *t2 = NULL;
1785 const char * dir =
".";
1786 char path[GIT_PATH_MAX];
1788 xx = chkgit(git,
"git_repository_discover",
1789 git_repository_discover(path,
sizeof(path), dir, 0,
"/"));
1791 fprintf(stderr,
"Could not discover repository\n");
1797 if (o.findopts.rename_threshold)
1798 o.findopts.flags |= GIT_DIFF_FIND_RENAMES;
1799 if (o.findopts.copy_threshold)
1800 o.findopts.flags |= GIT_DIFF_FIND_COPIES;
1804 treeish1 = (git->ac >= 1 ? git->av[0] : NULL);
1805 treeish2 = (git->ac >= 2 ? git->av[1] : NULL);
1808 xx = chkgit(git,
"treeish_to_tree",
1809 treeish_to_tree(&t1, git->R, treeish1));
1811 fprintf(stderr,
"Looking up first tree\n");
1816 xx = chkgit(git,
"treeish_to_tree",
1817 treeish_to_tree(&t2, git->R, treeish2));
1819 fprintf(stderr,
"Looking up second tree\n");
1831 xx = chkgit(git,
"git_diff_tree_to_tree",
1832 git_diff_tree_to_tree(&diff, git->R, t1, t2, &o.diffopts));
1833 else if (o.cache != CACHE_NORMAL) {
1835 xx = chkgit(git,
"treeish_to_tree",
1836 treeish_to_tree(&t1, git->R,
"HEAD"));
1838 if (o.cache == CACHE_NONE)
1839 xx = chkgit(git,
"git_diff_tree_to_workdir",
1840 git_diff_tree_to_workdir(&diff, git->R, t1, &o.diffopts));
1842 xx = chkgit(git,
"git_diff_tree_to_index",
1843 git_diff_tree_to_index(&diff, git->R, t1, NULL, &o.diffopts));
1846 xx = chkgit(git,
"git_diff_tree_to_index",
1847 git_diff_tree_to_index(&diff, git->R, t1, NULL, &o.diffopts));
1849 xx = chkgit(git,
"git_diff_tree_to_workdir_with_index",
1850 git_diff_tree_to_workdir_with_index(&diff, git->R, t1, &o.diffopts));
1852 xx = chkgit(git,
"git_diff_index_to_workdir",
1853 git_diff_index_to_workdir(&diff, git->R, NULL, &o.diffopts));
1856 if ((o.findopts.flags & GIT_DIFF_FIND_ALL) != 0)
1857 xx = chkgit(git,
"git_diff_find_similar",
1858 git_diff_find_similar(diff, &o.findopts));
1862 if (o.output != OUTPUT_DIFF)
1863 diff_print_stats(git, diff, &o);
1865 if (o.output & OUTPUT_DIFF) {
1867 fputs(colors[0], stdout);
1869 xx = chkgit(git,
"git_diff_print",
1870 git_diff_print(diff, o.format, color_printer, &o.color));
1873 fputs(colors[0], stdout);
1882 git_diff_free(diff);
1896 #if defined(WITH_LIBGIT2)
1901 FORMAT_PORCELAIN = 3,
1904 static void show_branch(git_repository *repo,
int format)
1907 const char *branch = NULL;
1908 git_reference *head = NULL;
1910 error = git_repository_head(&head, repo);
1912 if (error == GIT_EUNBORNBRANCH || error == GIT_ENOTFOUND)
1915 branch = git_reference_shorthand(head);
1917 check(error,
"failed to get current branch", NULL);
1919 if (format == FORMAT_LONG)
1920 printf(
"# On branch %s\n",
1921 branch ? branch :
"Not currently on any branch.");
1923 printf(
"## %s\n", branch ? branch :
"HEAD (no branch)");
1925 git_reference_free(head);
1928 static void print_long(git_repository *repo, git_status_list *status)
1930 size_t maxi = git_status_list_entrycount(status);
1932 const git_status_entry *s;
1934 int changes_in_index = 0;
1935 int changed_in_workdir = 0;
1936 int rm_in_workdir = 0;
1937 const char *old_path;
1938 const char *new_path;
1944 for (i = 0; i < maxi; ++
i) {
1945 char *istatus = NULL;
1947 s = git_status_byindex(status, i);
1949 if (s->status == GIT_STATUS_CURRENT)
1952 if (s->status & GIT_STATUS_WT_DELETED)
1955 if (s->status & GIT_STATUS_INDEX_NEW)
1956 istatus =
"new file: ";
1957 if (s->status & GIT_STATUS_INDEX_MODIFIED)
1958 istatus =
"modified: ";
1959 if (s->status & GIT_STATUS_INDEX_DELETED)
1960 istatus =
"deleted: ";
1961 if (s->status & GIT_STATUS_INDEX_RENAMED)
1962 istatus =
"renamed: ";
1963 if (s->status & GIT_STATUS_INDEX_TYPECHANGE)
1964 istatus =
"typechange:";
1966 if (istatus == NULL)
1970 printf(
"# Changes to be committed:\n");
1971 printf(
"# (use \"git reset HEAD <file>...\" to unstage)\n");
1976 old_path = s->head_to_index->old_file.path;
1977 new_path = s->head_to_index->new_file.path;
1979 if (old_path && new_path && strcmp(old_path, new_path))
1980 printf(
"#\t%s %s -> %s\n", istatus, old_path, new_path);
1982 printf(
"#\t%s %s\n", istatus, old_path ? old_path : new_path);
1986 changes_in_index = 1;
1992 for (i = 0; i < maxi; ++
i) {
1993 char *wstatus = NULL;
1995 s = git_status_byindex(status, i);
2002 if (s->status == GIT_STATUS_CURRENT || s->index_to_workdir == NULL)
2007 if (s->status & GIT_STATUS_WT_MODIFIED)
2008 wstatus =
"modified: ";
2009 if (s->status & GIT_STATUS_WT_DELETED)
2010 wstatus =
"deleted: ";
2011 if (s->status & GIT_STATUS_WT_RENAMED)
2012 wstatus =
"renamed: ";
2013 if (s->status & GIT_STATUS_WT_TYPECHANGE)
2014 wstatus =
"typechange:";
2016 if (wstatus == NULL)
2020 printf(
"# Changes not staged for commit:\n");
2021 printf(
"# (use \"git add%s <file>...\" to update what will be committed)\n", rm_in_workdir ?
"/rm" :
"");
2022 printf(
"# (use \"git checkout -- <file>...\" to discard changes in working directory)\n");
2027 old_path = s->index_to_workdir->old_file.path;
2028 new_path = s->index_to_workdir->new_file.path;
2030 if (old_path && new_path && strcmp(old_path, new_path))
2031 printf(
"#\t%s %s -> %s\n", wstatus, old_path, new_path);
2033 printf(
"#\t%s %s\n", wstatus, old_path ? old_path : new_path);
2037 changed_in_workdir = 1;
2043 for (i = 0; i < maxi; ++
i) {
2044 s = git_status_byindex(status, i);
2046 if (s->status == GIT_STATUS_WT_NEW) {
2049 printf(
"# Untracked files:\n");
2050 printf(
"# (use \"git add <file>...\" to include in what will be committed)\n");
2055 printf(
"#\t%s\n", s->index_to_workdir->old_file.path);
2061 for (i = 0; i < maxi; ++
i) {
2062 s = git_status_byindex(status, i);
2064 if (s->status == GIT_STATUS_IGNORED) {
2067 printf(
"# Ignored files:\n");
2068 printf(
"# (use \"git add -f <file>...\" to include in what will be committed)\n");
2073 printf(
"#\t%s\n", s->index_to_workdir->old_file.path);
2077 if (!changes_in_index && changed_in_workdir)
2078 printf(
"no changes added to commit (use \"git add\" and/or \"git commit -a\")\n");
2081 static void print_short(git_repository *repo, git_status_list *status)
2083 size_t maxi = git_status_list_entrycount(status);
2085 const git_status_entry *s;
2093 for (i = 0; i < maxi; ++
i) {
2094 s = git_status_byindex(status, i);
2096 if (s->status == GIT_STATUS_CURRENT)
2100 istatus = wstatus =
' ';
2103 if (s->status & GIT_STATUS_INDEX_NEW)
2105 if (s->status & GIT_STATUS_INDEX_MODIFIED)
2107 if (s->status & GIT_STATUS_INDEX_DELETED)
2109 if (s->status & GIT_STATUS_INDEX_RENAMED)
2111 if (s->status & GIT_STATUS_INDEX_TYPECHANGE)
2114 if (s->status & GIT_STATUS_WT_NEW) {
2119 if (s->status & GIT_STATUS_WT_MODIFIED)
2121 if (s->status & GIT_STATUS_WT_DELETED)
2123 if (s->status & GIT_STATUS_WT_RENAMED)
2125 if (s->status & GIT_STATUS_WT_TYPECHANGE)
2128 if (s->status & GIT_STATUS_IGNORED) {
2133 if (istatus ==
'?' && wstatus ==
'?')
2140 if (s->index_to_workdir &&
2141 s->index_to_workdir->new_file.mode == GIT_FILEMODE_COMMIT)
2143 git_submodule *sm = NULL;
2144 unsigned int smstatus = 0;
2146 if (!git_submodule_lookup( &sm, repo, s->index_to_workdir->new_file.path)
2147 && !git_submodule_status(&smstatus, sm))
2149 if (smstatus & GIT_SUBMODULE_STATUS_WD_MODIFIED)
2150 extra =
" (new commits)";
2151 else if (smstatus & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED)
2152 extra =
" (modified content)";
2153 else if (smstatus & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED)
2154 extra =
" (modified content)";
2155 else if (smstatus & GIT_SUBMODULE_STATUS_WD_UNTRACKED)
2156 extra =
" (untracked content)";
2158 git_submodule_free(sm);
2164 if (s->head_to_index) {
2165 a = s->head_to_index->old_file.path;
2166 b = s->head_to_index->new_file.path;
2168 if (s->index_to_workdir) {
2170 a = s->index_to_workdir->old_file.path;
2172 b = s->index_to_workdir->old_file.path;
2173 c = s->index_to_workdir->new_file.path;
2176 if (istatus ==
'R') {
2178 printf(
"%c%c %s %s %s%s\n", istatus, wstatus, a, b, c, extra);
2180 printf(
"%c%c %s %s%s\n", istatus, wstatus, a, b, extra);
2183 printf(
"%c%c %s %s%s\n", istatus, wstatus, a, c, extra);
2185 printf(
"%c%c %s%s\n", istatus, wstatus, a, extra);
2189 for (i = 0; i < maxi; ++
i) {
2190 s = git_status_byindex(status, i);
2192 if (s->status == GIT_STATUS_WT_NEW)
2193 printf(
"?? %s\n", s->index_to_workdir->old_file.path);
2197 static int print_submod(git_submodule *sm,
const char *name,
void *payload)
2199 int *count = payload;
2203 printf(
"# Submodules\n");
2206 printf(
"# - submodule '%s' at %s\n",
2207 git_submodule_name(sm), git_submodule_path(sm));
2217 #if defined(WITH_LIBGIT2)
2218 git_status_options opt = { GIT_STATUS_OPTIONS_VERSION, 0, 0, { NULL, 0} };
2219 const char * status_untracked_files =
xstrdup(
"all");
2220 const char * status_ignore_submodules =
xstrdup(
"all");
2222 _STATUS_BRANCH = (1 << 0),
2223 _STATUS_ZERO = (1 << 1),
2224 _STATUS_IGNORED = (1 << 2),
2225 _STATUS_SHOWSUBMOD = (1 << 3),
2227 int status_flags = 0;
2228 #define STATUS_ISSET(_a) (status_flags & _STATUS_##_a)
2229 int format = FORMAT_DEFAULT;
2231 struct poptOption statusOpts[] = {
2232 {
"short",
's', POPT_ARG_VAL, &format, FORMAT_SHORT,
2233 N_(
"Give the output in the short-format."), NULL },
2234 {
"long",
'\0', POPT_ARG_VAL, &format, FORMAT_LONG,
2235 N_(
"Give the output in the long-format."), NULL },
2236 {
"porcelain",
'\0', POPT_ARG_VAL, &format, FORMAT_PORCELAIN,
2237 N_(
"Give the output in a stable, easy-to-parse format for scripts."), NULL },
2238 {
"branch",
'b', POPT_BIT_SET, &status_flags, _STATUS_BRANCH,
2240 { NULL,
'z', POPT_BIT_SET, &status_flags, _STATUS_ZERO,
2242 {
"ignored",
'\0', POPT_BIT_SET, &status_flags, _STATUS_IGNORED,
2247 {
"untracked-files",
'u', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, &status_untracked_files, 0,
2248 N_(
"Show untracked files."),
N_(
"{no|normal|all}") },
2249 {
"ignore-submodules",
'\0', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, &status_ignore_submodules, 0,
2250 N_(
"Ignore sub-modules."),
N_(
"{all}") },
2251 {
"repeat",
'\0', POPT_ARG_INT, &repeat, 0,
2252 N_(
"Repeat every <sec> seconds."),
N_(
"<sec>") },
2253 {
"list-submodules",
'\0', POPT_BIT_SET, &status_flags, _STATUS_SHOWSUBMOD,
2261 git_status_list * list = NULL;
2264 opt.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
2266 opt.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED;
2267 opt.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX;
2268 opt.flags |= GIT_STATUS_OPT_SORT_CASE_SENSITIVELY;
2270 if (STATUS_ISSET(IGNORED)) {
2271 opt.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED;
2273 if (!strcmp(status_untracked_files,
"no")) {
2274 opt.flags &= ~GIT_STATUS_OPT_INCLUDE_UNTRACKED;
2275 opt.flags &= ~GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
2277 if (!strcmp(status_untracked_files,
"normal")) {
2278 opt.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED;
2279 opt.flags &= ~GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
2281 if (!strcmp(status_untracked_files,
"all")) {
2282 opt.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED;
2283 opt.flags |= GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
2285 if (!strcmp(status_ignore_submodules,
"all")) {
2286 opt.flags |= GIT_STATUS_OPT_EXCLUDE_SUBMODULES;
2289 if (format == FORMAT_DEFAULT)
2290 format = STATUS_ISSET(
ZERO) ? FORMAT_PORCELAIN : FORMAT_LONG;
2291 if (format == FORMAT_LONG)
2292 status_flags |= _STATUS_BRANCH;
2294 opt.pathspec.strings = (
char **) git->av;
2295 opt.pathspec.count = git->ac;
2300 printf(
"\033[H\033[2J");
2317 xx = chkgit(git,
"git_status_list_new",
2318 git_status_list_new(&list, git->R, &opt));
2320 if (STATUS_ISSET(BRANCH))
2321 show_branch(git->R, format);
2323 if (STATUS_ISSET(SHOWSUBMOD)) {
2324 int submod_count = 0;
2325 xx = chkgit(git,
"git_submodule_foreach",
2326 git_submodule_foreach(git->R, print_submod, &submod_count));
2329 if (format == FORMAT_LONG)
2330 print_long(git->R, list);
2332 print_short(git->R, list);
2334 git_status_list_free(list);
2348 git_status_list_free(list);
2351 status_untracked_files =
_free(status_untracked_files);
2352 status_ignore_submodules =
_free(status_ignore_submodules);
2362 #define ARGMINMAX(_min, _max) (int)(((_min) << 8) | ((_max) & 0xff))
2367 N_(
"Add file contents to the index."), NULL },
2369 {
"bisect",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2370 N_(
"Find by binary search the change that introduced a bug."), NULL },
2371 {
"branch",
'\0', POPT_ARG_MAINCALL, cmd_branch,
ARGMINMAX(0,0),
2372 N_(
"List, create, or delete branches."), NULL },
2373 {
"checkout",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2374 N_(
"Checkout a branch or paths to the working tree."), NULL },
2375 {
"clone",
'\0', POPT_ARG_MAINCALL, cmd_clone,
ARGMINMAX(0,0),
2376 N_(
"Clone a repository into a new directory."), NULL },
2379 N_(
"Record changes to the repository."), NULL },
2381 N_(
"Show changes between commits, commit and working tree, etc."), NULL },
2383 {
"fetch",
'\0', POPT_ARG_MAINCALL, cmd_fetch,
ARGMINMAX(0,0),
2384 N_(
"Download objects and refs from another repository."), NULL },
2385 {
"grep",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2386 N_(
"Print lines matching a pattern."), NULL },
2390 N_(
"Create an empty git repository or reinitialize an existing one."), NULL },
2392 {
"log",
'\0', POPT_ARG_MAINCALL, cmd_log,
ARGMINMAX(0,0),
2393 N_(
"Show commit logs."), NULL },
2394 {
"merge",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2395 N_(
"Join two or more development histories together."), NULL },
2396 {
"mv",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2397 N_(
"Move or rename a file, a directory, or a symlink."), NULL },
2398 {
"pull",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2399 N_(
"Fetch from and merge with another repository or a local branch."), NULL },
2400 {
"push",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2401 N_(
"Update remote refs along with associated objects."), NULL },
2402 {
"rebase",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2403 N_(
"Forward-port local commits to the updated upstream head."), NULL },
2404 {
"reset",
'\0', POPT_ARG_MAINCALL, cmd_reset,
ARGMINMAX(0,0),
2405 N_(
"Reset current HEAD to the specified state."), NULL },
2406 {
"rm",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2407 N_(
"Remove files from the working tree and from the index."), NULL },
2408 {
"show",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2409 N_(
"Show various types of objects."), NULL },
2412 N_(
"Show the working tree status."), NULL },
2414 {
"tag",
'\0', POPT_ARG_MAINCALL, cmd_tag,
ARGMINMAX(0,0),
2415 N_(
"Create, list, delete or verify a tag object signed with GPG."), NULL },
2420 {
"apply",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2421 N_(
"Apply a patch to files and/or to the index."), NULL },
2422 {
"checkout-index",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2423 N_(
"Copy files from the index to the working tree."), NULL },
2424 {
"commit-tree",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2425 N_(
"Create a new commit object."), NULL },
2426 {
"hash-object",
'\0', POPT_ARG_MAINCALL, cmd_hash_object,
ARGMINMAX(0,0),
2427 N_(
"Compute object ID and optionally creates a blob from a file."), NULL },
2428 {
"index-pack",
'\0', POPT_ARG_MAINCALL, cmd_index_pack,
ARGMINMAX(0,0),
2429 N_(
"Build pack index file for an existing packed archive."), NULL },
2430 {
"merge-file",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2431 N_(
"Run a three-way file merge."), NULL },
2432 {
"merge-index",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2433 N_(
"Run a merge for files needing merging."), NULL },
2434 {
"mktag",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2435 N_(
"Creates a tag object."), NULL },
2436 {
"mktree",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2437 N_(
"Build a tree-object from ls-tree formatted text."), NULL },
2438 {
"pack-objects",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2439 N_(
"Create a packed archive of objects."), NULL },
2440 {
"prune-packed",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2441 N_(
"Remove extra objects that are already in pack files."), NULL },
2442 {
"read-tree",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2443 N_(
"iReads tree information into the index."), NULL },
2444 {
"symbolic-ref",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2445 N_(
"iRead and modify symbolic refs."), NULL },
2446 {
"unpack-objects",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2447 N_(
"Unpack objects from a packed archive."), NULL },
2448 {
"update-index",
'\0', POPT_ARG_MAINCALL, cmd_update_index,
ARGMINMAX(0,0),
2449 N_(
"Register file contents in the working tree to the index."), NULL },
2450 {
"update-ref",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2451 N_(
"Update the object name stored in a ref safely."), NULL },
2452 {
"write-tree",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2453 N_(
"Create a tree object from the current index."), NULL },
2458 {
"archive",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2459 N_(
"Create a tar/zip archive of the files in the named tree object."), NULL },
2460 {
"cat-file",
'\0', POPT_ARG_MAINCALL, cmd_cat_file,
ARGMINMAX(0,0),
2461 N_(
"Provide content or type and size information for repository objects."), NULL },
2462 {
"diff-files",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2463 N_(
"Compares files in the working tree and the index."), NULL },
2464 {
"diff-index",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2465 N_(
"Compares content and mode of blobs between the index and repository."), NULL },
2466 {
"diff-tree",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2467 N_(
"Compares the content and mode of blobs found via two tree objects."), NULL },
2468 {
"for-each-ref",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2469 N_(
"Output information on each ref."), NULL },
2470 {
"ls-files",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2471 N_(
"Show information about files in the index and the working tree."), NULL },
2472 {
"ls-remote",
'\0', POPT_ARG_MAINCALL, cmd_ls_remote,
ARGMINMAX(0,0),
2473 N_(
"List references in a remote repository."), NULL },
2474 {
"ls-tree",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2475 N_(
"List the contents of a tree object."), NULL },
2476 {
"merge-base",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2477 N_(
"Find as good common ancestors as possible for a merge."), NULL },
2478 {
"name-rev",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2479 N_(
"Find symbolic names for given revs."), NULL },
2480 {
"pack-redundant",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2481 N_(
"Find redundant pack files."), NULL },
2482 {
"rev-list",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2483 N_(
"Lists commit objects in reverse chronological order."), NULL },
2484 {
"show-index",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2485 N_(
"Show packed archive index."), NULL },
2486 {
"show-ref",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2487 N_(
"List references in a local repository."), NULL },
2488 {
"unpack-file",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2489 N_(
"Creates a temporary file with blob contents."), NULL },
2490 {
"var",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2491 N_(
"Show a git logical variable."), NULL },
2492 {
"verify-pack",
'\0', POPT_ARG_MAINCALL, cmd_noop,
ARGMINMAX(0,0),
2493 N_(
"Validate packed git archive files."), NULL },
2498 {
"config",
'\0', POPT_ARG_MAINCALL, cmd_config,
ARGMINMAX(0,0),
2499 N_(
"Show git configuration."), NULL },
2500 {
"index",
'\0', POPT_ARG_MAINCALL, cmd_index,
ARGMINMAX(0,0),
2501 N_(
"Show git index."), NULL },
2502 {
"refs",
'\0', POPT_ARG_MAINCALL, cmd_refs,
ARGMINMAX(0,0),
2503 N_(
"Show git references."), NULL },
2504 {
"rev-parse",
'\0', POPT_ARG_MAINCALL,cmd_rev_parse,
ARGMINMAX(0,0),
2507 {
"index-pack-old",
'\0', POPT_ARG_MAINCALL, cmd_index_pack_old,
ARGMINMAX(0,0),
2508 N_(
"Index a <PACKFILE>."),
N_(
"<PACKFILE>") },
2515 static rpmRC rpmgitCmdHelp(
int argc,
char *argv[])
2518 struct poptOption * c;
2520 fprintf(fp,
"Commands:\n\n");
2521 for (c = _rpmgitCommandTable; c->longName != NULL; c++) {
2522 fprintf(fp,
" %s %s\n %s\n\n",
2523 c->longName, (c->argDescrip ? c->argDescrip :
""), c->descrip);
2528 static rpmRC rpmgitCmdRun(
int argc,
char *argv[])
2530 struct poptOption * c;
2534 if (argv == NULL || argv[0] == NULL)
2537 for (c = _rpmgitCommandTable; c->longName != NULL; c++) {
2538 rpmRC (*func) (
int argc,
char *argv[]) = NULL;
2540 if (strcmp(cmd, c->longName))
2544 rc = (*func) (argc, argv);
2566 {
"exec-path",
'\0', POPT_ARG_STRING, &
exec_path, 0,
2567 N_(
"Set exec path to <DIR>. env(GIT_EXEC_PATH)"),
N_(
"<DIR>") },
2568 {
"html-path",
'\0', POPT_ARG_STRING, &
html_path, 0,
2569 N_(
"Set html path to <DIR>. env(GIT_HTML_PATH)"),
N_(
"<DIR>") },
2570 {
"man-path",
'\0', POPT_ARG_STRING, &
man_path, 0,
2571 N_(
"Set man path to <DIR>."),
N_(
"<DIR>") },
2572 {
"info-path",
'\0', POPT_ARG_STRING, &
info_path, 0,
2573 N_(
"Set info path to <DIR>."),
N_(
"<DIR>") },
2575 {
"paginate",
'p', POPT_ARG_VAL, &
paginate, 1,
2576 N_(
"Set paginate. env(PAGER)"), NULL },
2577 {
"no-paginate",
'\0', POPT_ARG_VAL, &
paginate, 0,
2578 N_(
"Set paginate. env(PAGER)"), NULL },
2580 N_(
"Do not use replacement refs for objects."), NULL },
2581 {
"bare",
'\0', POPT_ARG_VAL, &
bare, 1,
2582 N_(
"Treat as a bare repository."), NULL },
2584 {
"git-dir",
'\0', POPT_ARG_STRING, &
_rpmgit_dir, 0,
2585 N_(
"Set git repository dir to <DIR>. env(GIT_DIR)"),
N_(
"<DIR>") },
2586 {
"work-tree",
'\0', POPT_ARG_STRING, &
_rpmgit_tree, 0,
2587 N_(
"Set git work tree to <DIR>. env(GIT_WORK_TREE)"),
N_(
"<DIR>") },
2589 { NULL,
'\0', POPT_ARG_INCLUDE_TABLE,
rpmgitCmds, 0,
2590 N_(
"The most commonly used git commands are::"),
2595 N_(
"Common options for all rpmio executables:"),
2602 { NULL, (char) -1, POPT_ARG_INCLUDE_TABLE, NULL, 0,
2604 usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n\
2605 [-p|--paginate|--no-pager] [--no-replace-objects]\n\
2606 [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n\
2607 [--help] COMMAND [ARGS]\n\
2609 The most commonly used git commands are:\n\
2610 add Add file contents to the index\n\
2611 bisect Find by binary search the change that introduced a bug\n\
2612 branch List, create, or delete branches\n\
2613 checkout Checkout a branch or paths to the working tree\n\
2614 clone Clone a repository into a new directory\n\
2615 commit Record changes to the repository\n\
2616 diff Show changes between commits, commit and working tree, etc\n\
2617 fetch Download objects and refs from another repository\n\
2618 grep Print lines matching a pattern\n\
2619 init Create an empty git repository or reinitialize an existing one\n\
2620 log Show commit logs\n\
2621 merge Join two or more development histories together\n\
2622 mv Move or rename a file, a directory, or a symlink\n\
2623 pull Fetch from and merge with another repository or a local branch\n\
2624 push Update remote refs along with associated objects\n\
2625 rebase Forward-port local commits to the updated upstream head\n\
2626 reset Reset current HEAD to the specified state\n\
2627 rm Remove files from the working tree and from the index\n\
2628 show Show various types of objects\n\
2629 status Show the working tree status\n\
2630 tag Create, list, delete or verify a tag object signed with GPG\n\
2632 See 'git COMMAND --help' for more information on a specific command.\n\
2646 #if defined(WITH_LIBGIT2)
2648 git_revwalk_free(git->walk);
2650 git_odb_free(git->odb);
2652 git_config_free(git->cfg);
2654 git_signature_free(git->S);
2656 git_commit_free(git->H);
2658 git_commit_free(git->C);
2660 git_tree_free(git->T);
2662 git_index_free(git->I);
2664 git_repository_free(git->R);
2668 git_threads_shutdown();
2688 git->shared_umask = 0;
2694 git->user_email =
_free(git->user_email);
2695 git->user_name =
_free(git->user_name);
2697 git->core_repositoryformatversion = 0;
2701 git->workdir =
_free(git->workdir);
2702 git->repodir =
_free(git->repodir);
2706 git->con = poptFreeContext(git->con);
2709 git->fn =
_free(git->fn);
2725 if (_rpmgitPool == NULL) {
2731 memset(((
char *)git)+
sizeof(git->_item), 0,
sizeof(*git)-
sizeof(git->_item));
2737 static const char * _gitI_init =
"\
2745 if (_rpmgitI == NULL)
2752 static char * _av[] = { (
char *)
"rpmgit", NULL };
2753 int initialize = (!(flags & 0x80000000) || _rpmgitI == NULL);
2754 rpmgit git = (flags & 0x80000000)
2757 poptOption
opts = (poptOption) _opts;
2762 fprintf(stderr,
"==> %s(%p, 0x%x) git %p fn %s\n", __FUNCTION__, av, flags, git, fn);
2764 if (av == NULL) av = _av;
2771 git->fn = (fn ?
xstrdup(fn) : NULL);
2774 #if defined(WITH_LIBGIT2)
2785 git_libgit2_version(&git->major, &git->minor, &git->rev);
2787 if (git->fn && git->R == NULL) {
2788 git->repodir =
xstrdup(git->fn);
2789 xx = chkgit(git,
"git_repository_open",
2790 git_repository_open((git_repository **)&git->R, git->repodir));
2793 if (git->fn &&
Stat(git->fn, &sb) == 0)
2796 assert(xx == 0 && git->R != NULL && git->repodir != NULL);
2803 static const char _rpmgitI_init[] =
"%{?_rpmgitI_init}";
2804 const char * s =
rpmExpand(_rpmgitI_init, _gitI_init, NULL);
2810 for (i = 0; (arg = sav[
i]) != NULL; i++) {
2829 struct poptOption * c;
2830 rpmRC (*handler) (
int argc,
char *argv[]);
2835 fprintf(stderr,
"==> %s(%p,%s,%p)\n", __FUNCTION__, git, str, resultp);
2837 if (git == NULL) git =
rpmgitI();
2840 if (git->av == NULL || git->av[0] == NULL)
2843 for (c = rpmgitCmds; c->longName != NULL; c++) {
2844 if (strcmp(cmd, c->longName))
2847 minargs = (c->val >> 8) & 0xff;
2848 maxargs = (c->val ) & 0xff;
2851 if (c->longName == NULL) {
2852 fprintf(stderr,
"Unknown command '%s'\n", cmd);
2855 if (minargs && git->ac < minargs) {
2856 fprintf(stderr,
"Not enough arguments for \"git %s\"\n", c->longName);
2859 if (maxargs && git->ac > maxargs) {
2860 fprintf(stderr,
"Too many arguments for \"git %s\"\n", c->longName);
2868 rc = (*handler)(git->ac, (
char **)git->av);
const char const double d
#define SPEW(_t, _rc, _git)
#define ARGMINMAX(_min, _max)
void rpmgitPrintOid(const char *msg, const void *_oidp, void *_fp)
const char const char * cmd
char * xstrdup(const char *str)
char * gidToGname(gid_t gid)
int argvAppend(ARGV_t *argvp, ARGV_t av)
Append one argv array to another.
int Stat(const char *path, struct stat *st)
stat(2) clone.
rpmRC rpmgitCmdDiff(int argc, char *argv[])
int Open(const char *path, int flags, mode_t mode)
open(2) clone.
static int no_replace_objects
rpmgit rpmgitLink(rpmgit git)
Reference a git wrapper instance.
int rpmgitTree(rpmgit git)
static int rpmgitPopt(rpmgit git, int argc, char *argv[], poptOption opts)
void rpmgitPrintSig(const char *msg, const void *___S, void *_fp)
static void rpmlog(int code, const char *fmt,...)
void rpmgitPrintCommit(rpmgit git, void *___C, void *_fp)
static void rpmgitFini(void *_git)
static struct poptOption rpmgitCmds[]
void rpmgitPrintTag(rpmgit git, void *_tag, void *_fp)
void rpmgitPrintRepo(rpmgit git, void *___R, void *_fp)
static const char * fmtBits(uint32_t flags, KEY tbl[], size_t ntbl, char *t)
rpmRC rpmgitCmdAdd(int argc, char *argv[])
Yet Another syslog(3) API clone.
void rpmgitPrintTree(void *___T, void *_fp)
const char const bson_bool_t v
int rpmgitAddFile(rpmgit git, const char *fn)
rpmgit rpmgitFree(rpmgit git)
Destroy a git wrapper.
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
static const char * tblName(uint32_t v, KEY *tbl, size_t ntbl)
int argvCount(const ARGV_t argv)
Return no.
int rpmgitWalk(rpmgit git)
const char const bson_oid_t * oid
const char const bson * command
static const char * exec_path
const char const bson * data
const char const bson const bson int limit
int rpmgitConfig(rpmgit git)
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
static enum FN_e filenames
void rpmgitPrintIndex(void *___I, void *_fp)
static rpmgit rpmgitI(void)
const char const char * user
int rpmgitClose(rpmgit git)
static rpmgit rpmgitGetPool(rpmioPool pool)
static const char * html_path
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
const char const char int arg
static struct poptOption rpmgitOpts[]
const char const bson int mongo_write_concern int flags
int rpmgitWrite(rpmgit git)
void argvPrint(const char *msg, ARGV_t argv, FILE *fp)
Print argv array elements.
rpmRC rpmgitCmdInit(int argc, char *argv[])
static void output(int indent, int *offset, const char *fmt,...)
int rpmgitOpen(rpmgit git, const char *repodir)
enum rpmRC_e rpmRC
RPM return codes.
const char const char const char * opts
rpmRC rpmgitCmdCommit(int argc, char *argv[])
static int snprintf(char *buf, int nb, const char *fmt,...)
int rpmgitCommit(rpmgit git, const char *msg)
int rpmgitInit(rpmgit git, void *initopts)
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
char * stpcpy(char *dest, const char *src)
static int _rpmgit_threads
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
char * uidToUname(uid_t uid)
rpmRC rpmgitRun(rpmgit git, const char *str, const char **resultp)
Execute git string.
int argvSplit(ARGV_t *argvp, const char *str, const char *seps)
Split a string into an argv array.
int rpmgitInfo(rpmgit git)
rpmRC rpmgitCmdStatus(int argc, char *argv[])
static const char * info_path
const char * _rpmgit_tree
struct poptOption rpmioAllPoptTable[]
Popt option table for options shared by all modes and executables.
rpmgit rpmgitNew(char **av, uint32_t flags, void *_opts)
Create and load a git wrapper.
static const char * man_path
const char const bson const bson int int int options
char * Realpath(const char *path, char *resolved_path)
realpath(3) clone.
void rpmgitPrintHead(rpmgit git, void *___H, void *_fp)
void rpmgitPrintTime(const char *msg, time_t _Ctime, void *_fp)
const char * rpmgitOid(rpmgit git, const void *_oid)
int rpmgitRead(rpmgit git)