2005-04-19 02:39:48 +08:00
|
|
|
#ifndef COMMIT_H
|
|
|
|
#define COMMIT_H
|
|
|
|
|
|
|
|
#include "object.h"
|
|
|
|
#include "tree.h"
|
2007-09-10 18:35:06 +08:00
|
|
|
#include "strbuf.h"
|
2007-04-17 07:05:10 +08:00
|
|
|
#include "decorate.h"
|
2005-04-19 02:39:48 +08:00
|
|
|
|
|
|
|
struct commit_list {
|
|
|
|
struct commit *item;
|
|
|
|
struct commit_list *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct commit {
|
|
|
|
struct object object;
|
2006-06-18 09:26:18 +08:00
|
|
|
void *util;
|
2007-11-03 04:32:58 +08:00
|
|
|
unsigned int indegree;
|
2005-04-19 02:39:48 +08:00
|
|
|
unsigned long date;
|
|
|
|
struct commit_list *parents;
|
|
|
|
struct tree *tree;
|
2005-05-26 10:26:28 +08:00
|
|
|
char *buffer;
|
2005-04-19 02:39:48 +08:00
|
|
|
};
|
|
|
|
|
[PATCH] Avoid wasting memory in git-rev-list
As pointed out on the list, git-rev-list can use a lot of memory.
One low-hanging fruit is to free the commit buffer for commits that we
parse. By default, parse_commit() will save away the buffer, since a lot
of cases do want it, and re-reading it continually would be unnecessary.
However, in many cases the buffer isn't actually necessary and saving it
just wastes memory.
We could just free the buffer ourselves, but especially in git-rev-list,
we actually end up using the helper functions that automatically add
parent commits to the commit lists, so we don't actually control the
commit parsing directly.
Instead, just make this behaviour of "parse_commit()" a global flag.
Maybe this is a bit tasteless, but it's very simple, and it makes a
noticable difference in memory usage.
Before the change:
[torvalds@g5 linux]$ /usr/bin/time git-rev-list v2.6.12..HEAD > /dev/null
0.26user 0.02system 0:00.28elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+3714minor)pagefaults 0swaps
after the change:
[torvalds@g5 linux]$ /usr/bin/time git-rev-list v2.6.12..HEAD > /dev/null
0.26user 0.00system 0:00.27elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+2433minor)pagefaults 0swaps
note how the minor faults have decreased from 3714 pages to 2433 pages.
That's all due to the fewer anonymous pages allocated to hold the comment
buffers and their metadata.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-09-16 05:43:17 +08:00
|
|
|
extern int save_commit_buffer;
|
2005-04-19 02:39:48 +08:00
|
|
|
extern const char *commit_type;
|
|
|
|
|
2007-04-17 07:05:10 +08:00
|
|
|
/* While we can decorate any object with a name, it's only used for commits.. */
|
|
|
|
extern struct decoration name_decoration;
|
|
|
|
struct name_decoration {
|
|
|
|
struct name_decoration *next;
|
2010-06-19 09:37:33 +08:00
|
|
|
int type;
|
2007-04-17 07:05:10 +08:00
|
|
|
char name[1];
|
|
|
|
};
|
|
|
|
|
2005-06-03 23:05:39 +08:00
|
|
|
struct commit *lookup_commit(const unsigned char *sha1);
|
|
|
|
struct commit *lookup_commit_reference(const unsigned char *sha1);
|
2005-08-21 17:51:10 +08:00
|
|
|
struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
|
|
|
|
int quiet);
|
2010-11-03 03:59:07 +08:00
|
|
|
struct commit *lookup_commit_reference_by_name(const char *name);
|
2005-04-19 02:39:48 +08:00
|
|
|
|
2011-09-17 19:57:45 +08:00
|
|
|
/*
|
|
|
|
* Look up object named by "sha1", dereference tag as necessary,
|
|
|
|
* get a commit and return it. If "sha1" does not dereference to
|
|
|
|
* a commit, use ref_name to report an error and die.
|
|
|
|
*/
|
|
|
|
struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_name);
|
|
|
|
|
2011-02-05 18:52:20 +08:00
|
|
|
int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size);
|
2005-04-19 02:39:48 +08:00
|
|
|
int parse_commit(struct commit *item);
|
|
|
|
|
2010-07-22 21:18:30 +08:00
|
|
|
/* Find beginning and length of commit subject. */
|
|
|
|
int find_commit_subject(const char *commit_buffer, const char **subject);
|
|
|
|
|
2010-11-27 09:58:14 +08:00
|
|
|
struct commit_list *commit_list_insert(struct commit *item,
|
|
|
|
struct commit_list **list);
|
2008-06-28 00:21:55 +08:00
|
|
|
unsigned commit_list_count(const struct commit_list *l);
|
2010-11-27 09:58:14 +08:00
|
|
|
struct commit_list *commit_list_insert_by_date(struct commit *item,
|
|
|
|
struct commit_list **list);
|
|
|
|
void commit_list_sort_by_date(struct commit_list **list);
|
2005-04-24 09:47:23 +08:00
|
|
|
|
2005-04-19 02:39:48 +08:00
|
|
|
void free_commit_list(struct commit_list *list);
|
|
|
|
|
2005-06-06 00:02:03 +08:00
|
|
|
/* Commit formats */
|
|
|
|
enum cmit_fmt {
|
|
|
|
CMIT_FMT_RAW,
|
|
|
|
CMIT_FMT_MEDIUM,
|
|
|
|
CMIT_FMT_DEFAULT = CMIT_FMT_MEDIUM,
|
2005-06-27 08:50:46 +08:00
|
|
|
CMIT_FMT_SHORT,
|
|
|
|
CMIT_FMT_FULL,
|
2005-11-10 14:15:27 +08:00
|
|
|
CMIT_FMT_FULLER,
|
2005-08-09 13:15:40 +08:00
|
|
|
CMIT_FMT_ONELINE,
|
2006-04-19 07:45:27 +08:00
|
|
|
CMIT_FMT_EMAIL,
|
2007-02-23 08:35:03 +08:00
|
|
|
CMIT_FMT_USERFORMAT,
|
2006-04-16 14:46:36 +08:00
|
|
|
|
2010-05-14 17:31:35 +08:00
|
|
|
CMIT_FMT_UNSPECIFIED
|
2005-06-06 00:02:03 +08:00
|
|
|
};
|
|
|
|
|
2011-03-16 15:08:34 +08:00
|
|
|
struct pretty_print_context {
|
2011-05-27 06:27:49 +08:00
|
|
|
enum cmit_fmt fmt;
|
2009-10-19 23:48:08 +08:00
|
|
|
int abbrev;
|
|
|
|
const char *subject;
|
|
|
|
const char *after_subject;
|
2011-05-27 06:28:17 +08:00
|
|
|
int preserve_subject;
|
2009-10-19 23:48:08 +08:00
|
|
|
enum date_mode date_mode;
|
|
|
|
int need_8bit_cte;
|
2010-01-21 05:59:36 +08:00
|
|
|
int show_notes;
|
2009-10-19 23:48:10 +08:00
|
|
|
struct reflog_walk_info *reflog_info;
|
2010-11-03 03:59:08 +08:00
|
|
|
const char *output_encoding;
|
2009-10-19 23:48:08 +08:00
|
|
|
};
|
|
|
|
|
2010-04-14 04:31:12 +08:00
|
|
|
struct userformat_want {
|
|
|
|
unsigned notes:1;
|
|
|
|
};
|
|
|
|
|
2009-08-11 00:22:18 +08:00
|
|
|
extern int has_non_ascii(const char *text);
|
2008-04-08 08:11:34 +08:00
|
|
|
struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
|
2010-11-03 03:59:08 +08:00
|
|
|
extern char *logmsg_reencode(const struct commit *commit,
|
|
|
|
const char *output_encoding);
|
2008-10-22 04:55:57 +08:00
|
|
|
extern char *reencode_commit_message(const struct commit *commit,
|
|
|
|
const char **encoding_p);
|
2008-04-08 08:11:34 +08:00
|
|
|
extern void get_commit_format(const char *arg, struct rev_info *);
|
2011-04-08 02:26:23 +08:00
|
|
|
extern const char *format_subject(struct strbuf *sb, const char *msg,
|
|
|
|
const char *line_separator);
|
2010-04-14 04:31:12 +08:00
|
|
|
extern void userformat_find_requirements(const char *fmt, struct userformat_want *w);
|
2007-09-10 18:35:06 +08:00
|
|
|
extern void format_commit_message(const struct commit *commit,
|
2009-10-16 13:59:41 +08:00
|
|
|
const char *format, struct strbuf *sb,
|
2009-10-19 23:48:08 +08:00
|
|
|
const struct pretty_print_context *context);
|
2011-05-27 06:27:49 +08:00
|
|
|
extern void pretty_print_commit(const struct pretty_print_context *pp,
|
|
|
|
const struct commit *commit,
|
|
|
|
struct strbuf *sb);
|
2011-05-27 06:27:24 +08:00
|
|
|
extern void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
|
|
|
|
struct strbuf *sb);
|
2011-05-27 06:27:49 +08:00
|
|
|
void pp_user_info(const struct pretty_print_context *pp,
|
|
|
|
const char *what, struct strbuf *sb,
|
|
|
|
const char *line, const char *encoding);
|
|
|
|
void pp_title_line(const struct pretty_print_context *pp,
|
2008-02-19 11:56:08 +08:00
|
|
|
const char **msg_p,
|
|
|
|
struct strbuf *sb,
|
|
|
|
const char *encoding,
|
2008-03-15 15:09:20 +08:00
|
|
|
int need_8bit_cte);
|
2011-05-27 06:27:49 +08:00
|
|
|
void pp_remainder(const struct pretty_print_context *pp,
|
2008-02-19 11:56:08 +08:00
|
|
|
const char **msg_p,
|
|
|
|
struct strbuf *sb,
|
|
|
|
int indent);
|
|
|
|
|
2005-06-01 23:34:23 +08:00
|
|
|
|
2005-04-24 09:47:23 +08:00
|
|
|
/** Removes the first commit from a list sorted by date, and adds all
|
|
|
|
* of its parents.
|
|
|
|
**/
|
2007-06-07 15:04:01 +08:00
|
|
|
struct commit *pop_most_recent_commit(struct commit_list **list,
|
2005-04-24 11:29:22 +08:00
|
|
|
unsigned int mark);
|
2005-04-24 09:47:23 +08:00
|
|
|
|
2005-06-06 23:39:40 +08:00
|
|
|
struct commit *pop_commit(struct commit_list **stack);
|
|
|
|
|
2006-01-08 10:52:42 +08:00
|
|
|
void clear_commit_marks(struct commit *commit, unsigned int mark);
|
2011-10-02 00:16:08 +08:00
|
|
|
void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark);
|
2006-01-08 10:52:42 +08:00
|
|
|
|
2005-07-07 00:39:34 +08:00
|
|
|
/*
|
|
|
|
* Performs an in-place topological sort of list supplied.
|
|
|
|
*
|
|
|
|
* invariant of resulting list is:
|
|
|
|
* a reachable from b => ord(b) < ord(a)
|
2006-02-16 14:05:33 +08:00
|
|
|
* in addition, when lifo == 0, commits on parallel tracks are
|
|
|
|
* sorted in the dates order.
|
2005-07-07 00:39:34 +08:00
|
|
|
*/
|
2006-02-16 14:05:33 +08:00
|
|
|
void sort_in_topological_order(struct commit_list ** list, int lifo);
|
2006-04-07 14:58:51 +08:00
|
|
|
|
|
|
|
struct commit_graft {
|
|
|
|
unsigned char sha1[20];
|
2006-10-31 03:09:06 +08:00
|
|
|
int nr_parent; /* < 0 if shallow commit */
|
2006-04-07 14:58:51 +08:00
|
|
|
unsigned char parent[FLEX_ARRAY][20]; /* more */
|
|
|
|
};
|
2011-08-18 20:29:35 +08:00
|
|
|
typedef int (*each_commit_graft_fn)(const struct commit_graft *, void *);
|
2006-04-07 14:58:51 +08:00
|
|
|
|
|
|
|
struct commit_graft *read_graft_line(char *buf, int len);
|
|
|
|
int register_commit_graft(struct commit_graft *, int);
|
2008-02-26 05:46:07 +08:00
|
|
|
struct commit_graft *lookup_commit_graft(const unsigned char *sha1);
|
2006-04-07 14:58:51 +08:00
|
|
|
|
2006-07-02 17:49:38 +08:00
|
|
|
extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2, int cleanup);
|
2008-07-30 13:04:14 +08:00
|
|
|
extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos, int cleanup);
|
2008-06-28 00:22:00 +08:00
|
|
|
extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);
|
2006-06-29 21:17:32 +08:00
|
|
|
|
2006-10-31 03:09:06 +08:00
|
|
|
extern int register_shallow(const unsigned char *sha1);
|
2006-10-31 03:09:53 +08:00
|
|
|
extern int unregister_shallow(const unsigned char *sha1);
|
2011-08-18 20:29:35 +08:00
|
|
|
extern int for_each_commit_graft(each_commit_graft_fn, void *);
|
2007-01-22 14:22:23 +08:00
|
|
|
extern int is_repository_shallow(void);
|
2006-10-31 03:09:06 +08:00
|
|
|
extern struct commit_list *get_shallow_commits(struct object_array *heads,
|
2006-10-31 03:09:53 +08:00
|
|
|
int depth, int shallow_flag, int not_shallow_flag);
|
2006-10-31 03:09:06 +08:00
|
|
|
|
2009-01-26 22:13:24 +08:00
|
|
|
int is_descendant_of(struct commit *, struct commit_list *);
|
2007-01-09 15:22:31 +08:00
|
|
|
int in_merge_bases(struct commit *, struct commit **, int);
|
2007-09-18 08:06:44 +08:00
|
|
|
|
2011-05-08 01:58:07 +08:00
|
|
|
extern int interactive_add(int argc, const char **argv, const char *prefix, int patch);
|
2009-08-13 20:29:41 +08:00
|
|
|
extern int run_add_interactive(const char *revision, const char *patch_mode,
|
|
|
|
const char **pathspec);
|
2007-09-18 08:06:44 +08:00
|
|
|
|
2007-11-06 05:22:34 +08:00
|
|
|
static inline int single_parent(struct commit *commit)
|
|
|
|
{
|
|
|
|
return commit->parents && !commit->parents->next;
|
|
|
|
}
|
|
|
|
|
2008-06-28 00:22:03 +08:00
|
|
|
struct commit_list *reduce_heads(struct commit_list *heads);
|
|
|
|
|
2011-11-08 08:21:32 +08:00
|
|
|
struct commit_extra_header {
|
|
|
|
struct commit_extra_header *next;
|
|
|
|
char *key;
|
|
|
|
char *value;
|
|
|
|
size_t len;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern void append_merge_tag_headers(struct commit_list *parents,
|
|
|
|
struct commit_extra_header ***tail);
|
|
|
|
|
2011-12-15 21:47:22 +08:00
|
|
|
extern int commit_tree(const struct strbuf *msg, unsigned char *tree,
|
2011-11-08 08:21:32 +08:00
|
|
|
struct commit_list *parents, unsigned char *ret,
|
commit: teach --gpg-sign option
This uses the gpg-interface.[ch] to allow signing the commit, i.e.
$ git commit --gpg-sign -m foo
You need a passphrase to unlock the secret key for
user: "Junio C Hamano <gitster@pobox.com>"
4096-bit RSA key, ID 96AFE6CB, created 2011-10-03 (main key ID 713660A7)
[master 8457d13] foo
1 files changed, 1 insertions(+), 0 deletions(-)
The lines of GPG detached signature are placed in a new multi-line header
field, instead of tucking the signature block at the end of the commit log
message text (similar to how signed tag is done), for multiple reasons:
- The signature won't clutter output from "git log" and friends if it is
in the extra header. If we place it at the end of the log message, we
would need to teach "git log" and friends to strip the signature block
with an option.
- Teaching new versions of "git log" and "gitk" to optionally verify and
show signatures is cleaner if we structurally know where the signature
block is (instead of scanning in the commit log message).
- The signature needs to be stripped upon various commit rewriting
operations, e.g. rebase, filter-branch, etc. They all already ignore
unknown headers, but if we place signature in the log message, all of
these tools (and third-party tools) also need to learn how a signature
block would look like.
- When we added the optional encoding header, all the tools (both in tree
and third-party) that acts on the raw commit object should have been
fixed to ignore headers they do not understand, so it is not like that
new header would be more likely to break than extra text in the commit.
A commit made with the above sample sequence would look like this:
$ git cat-file commit HEAD
tree 3cd71d90e3db4136e5260ab54599791c4f883b9d
parent b87755351a47b09cb27d6913e6e0e17e6254a4d4
author Junio C Hamano <gitster@pobox.com> 1317862251 -0700
committer Junio C Hamano <gitster@pobox.com> 1317862251 -0700
gpgsig -----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
iQIcBAABAgAGBQJOjPtrAAoJELC16IaWr+bL4TMP/RSe2Y/jYnCkds9unO5JEnfG
...
=dt98
-----END PGP SIGNATURE-----
foo
but "git log" (unless you ask for it with --pretty=raw) output is not
cluttered with the signature information.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-06 08:23:20 +08:00
|
|
|
const char *author, const char *sign_commit);
|
2011-11-08 08:21:32 +08:00
|
|
|
|
2011-12-23 03:27:26 +08:00
|
|
|
extern int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,
|
2011-11-08 08:21:32 +08:00
|
|
|
struct commit_list *parents, unsigned char *ret,
|
commit: teach --gpg-sign option
This uses the gpg-interface.[ch] to allow signing the commit, i.e.
$ git commit --gpg-sign -m foo
You need a passphrase to unlock the secret key for
user: "Junio C Hamano <gitster@pobox.com>"
4096-bit RSA key, ID 96AFE6CB, created 2011-10-03 (main key ID 713660A7)
[master 8457d13] foo
1 files changed, 1 insertions(+), 0 deletions(-)
The lines of GPG detached signature are placed in a new multi-line header
field, instead of tucking the signature block at the end of the commit log
message text (similar to how signed tag is done), for multiple reasons:
- The signature won't clutter output from "git log" and friends if it is
in the extra header. If we place it at the end of the log message, we
would need to teach "git log" and friends to strip the signature block
with an option.
- Teaching new versions of "git log" and "gitk" to optionally verify and
show signatures is cleaner if we structurally know where the signature
block is (instead of scanning in the commit log message).
- The signature needs to be stripped upon various commit rewriting
operations, e.g. rebase, filter-branch, etc. They all already ignore
unknown headers, but if we place signature in the log message, all of
these tools (and third-party tools) also need to learn how a signature
block would look like.
- When we added the optional encoding header, all the tools (both in tree
and third-party) that acts on the raw commit object should have been
fixed to ignore headers they do not understand, so it is not like that
new header would be more likely to break than extra text in the commit.
A commit made with the above sample sequence would look like this:
$ git cat-file commit HEAD
tree 3cd71d90e3db4136e5260ab54599791c4f883b9d
parent b87755351a47b09cb27d6913e6e0e17e6254a4d4
author Junio C Hamano <gitster@pobox.com> 1317862251 -0700
committer Junio C Hamano <gitster@pobox.com> 1317862251 -0700
gpgsig -----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
iQIcBAABAgAGBQJOjPtrAAoJELC16IaWr+bL4TMP/RSe2Y/jYnCkds9unO5JEnfG
...
=dt98
-----END PGP SIGNATURE-----
foo
but "git log" (unless you ask for it with --pretty=raw) output is not
cluttered with the signature information.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-06 08:23:20 +08:00
|
|
|
const char *author, const char *sign_commit,
|
2011-11-08 08:21:32 +08:00
|
|
|
struct commit_extra_header *);
|
|
|
|
|
2012-01-06 02:54:14 +08:00
|
|
|
extern struct commit_extra_header *read_commit_extra_headers(struct commit *, const char **);
|
|
|
|
extern struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
|
2011-11-09 07:38:07 +08:00
|
|
|
|
2011-11-08 08:21:32 +08:00
|
|
|
extern void free_commit_extra_headers(struct commit_extra_header *extra);
|
make commit_tree a library function
Until now, this has been part of the commit-tree builtin.
However, it is already used by other builtins (like commit,
merge, and notes), and it would be useful to access it from
library code.
The check_valid helper has to come along, too, but is given
a more library-ish name of "assert_sha1_type".
Otherwise, the code is unchanged. There are still a few
rough edges for a library function, like printing the utf8
warning to stderr, but we can address those if and when they
come up as inappropriate.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-02 08:05:23 +08:00
|
|
|
|
2011-11-08 05:26:22 +08:00
|
|
|
struct merge_remote_desc {
|
|
|
|
struct object *obj; /* the named object, could be a tag */
|
|
|
|
const char *name;
|
|
|
|
};
|
|
|
|
#define merge_remote_util(commit) ((struct merge_remote_desc *)((commit)->util))
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Given "name" from the command line to merge, find the commit object
|
|
|
|
* and return it, while storing merge_remote_desc in its ->util field,
|
|
|
|
* to allow callers to tell if we are told to merge a tag.
|
|
|
|
*/
|
|
|
|
struct commit *get_merge_parent(const char *name);
|
|
|
|
|
2011-10-19 06:53:23 +08:00
|
|
|
extern int parse_signed_commit(const unsigned char *sha1,
|
|
|
|
struct strbuf *message, struct strbuf *signature);
|
2005-04-19 02:39:48 +08:00
|
|
|
#endif /* COMMIT_H */
|