description (50 characters is the soft limit, see DISCUSSION
in git-commit(1)), and should skip the full stop
- the body should provide a meaningful commit message, which:
- - uses the imperative, present tense: "change",
- not "changed" or "changes".
- - includes motivation for the change, and contrasts
- its implementation with previous behaviour
+ . explains the problem the change tries to solve, iow, what
+ is wrong with the current code without the change.
+ . justifies the way the change solves the problem, iow, why
+ the result with the change is better.
+ . alternate solutions considered but discarded, if any.
+ - describe changes in imperative mood, e.g. "make xyzzy do frotz"
+ instead of "[This patch] makes xyzzy do frotz" or "[I] changed
+ xyzzy to do frotz", as if you are giving orders to the codebase
+ to change its behaviour.
+ - try to make sure your explanation can be understood without
+ external resources. Instead of giving a URL to a mailing list
+ archive, summarize the relevant points of the discussion.
- add a "Signed-off-by: Your Name <you@example.com>" line to the
commit message (or just use the option "-s" when committing)
to confirm that you agree to the Developer's Certificate of Origin
commit message and generate a series of patches from your
repository. It is a good discipline.
-Describe the technical detail of the change(s).
+Give an explanation for the change(s) that is detailed enough so
+that people can judge if it is good thing to do, without reading
+the actual patch text to determine how well the code does what
+the explanation promises to do.
If your description starts to get too long, that's a sign that you
probably need to split up your commit to finer grained pieces.
the code, are the most beautiful patches. Descriptions that summarise
the point in the subject well, and describe the motivation for the
change, the approach taken by the change, and if relevant how this
-differs substantially from the prior version, can be found on Usenet
-archives back into the late 80's. Consider it like good Netiquette,
-but for code.
+differs substantially from the prior version, are all good things
+to have.
Oh, another thing. I am picky about whitespaces. Make sure your
changes do not trigger errors with the sample pre-commit hook shipped
If true, git will warn you if the ref name you passed it is ambiguous
and might match multiple refs in the .git/refs/ tree. True by default.
-core.abbrevguard::
- Even though git makes sure that it uses enough hexdigits to show
- an abbreviated object name unambiguously, as more objects are
- added to the repository over time, a short name that used to be
- unique will stop being unique. Git uses this many extra hexdigits
- that are more than necessary to make the object name currently
- unique, in the hope that its output will stay unique a bit longer.
- Defaults to 0.
-
core.compression::
An integer -1..9, indicating a default compression level.
-1 is the zlib default. 0 means no compression,
combined diff format
--------------------
-"git-diff-tree", "git-diff-files" and "git-diff" can take '-c' or
-'--cc' option to produce 'combined diff'. For showing a merge commit
-with "git log -p", this is the default format; you can force showing
-full diff with the '-m' option.
+Any diff-generating command can take the `-c` or `--cc` option to
+produce a 'combined diff' when showing a merge. This is the default
+format when showing merges with linkgit:git-diff[1] or
+linkgit:git-show[1]. Note also that you can give the `-m' option to any
+of these commands to force generation of diffs with individual parents
+of a merge.
+
A 'combined diff' format looks like this:
------------
-----------
Reads the supplied diff output (i.e. "a patch") and applies it to files.
With the `--index` option the patch is also applied to the index, and
-with the `--cache` option the patch is only applied to the index.
+with the `--cached` option the patch is only applied to the index.
Without these options, the command applies the patch only to files,
and does not require them to be in a git repository.
-u[<mode>]::
--untracked-files[=<mode>]::
- Show untracked files (Default: 'all').
+ Show untracked files.
+
-The mode parameter is optional, and is used to specify
-the handling of untracked files.
+The mode parameter is optional (defaults to 'all'), and is used to
+specify the handling of untracked files; when -u is not used, the
+default is 'normal', i.e. show untracked files and directories.
+
The possible options are:
+
- 'normal' - Shows untracked files and directories
- 'all' - Also shows individual files in untracked directories.
+
-See linkgit:git-config[1] for configuration variable
-used to change the default for when the option is not
-specified.
+The default can be changed using the status.showUntrackedFiles
+configuration variable documented in linkgit:git-config[1].
-v::
--verbose::
--------
An example directly producing formatted text. Show the most recent
-3 tagged commits::
+3 tagged commits:
------------
#!/bin/sh
A simple example showing the use of shell eval on the output,
-demonstrating the use of --shell. List the prefixes of all heads::
+demonstrating the use of --shell. List the prefixes of all heads:
------------
#!/bin/sh
A bit more elaborate report on tags, demonstrating that the format
-may be an entire script::
+may be an entire script:
------------
#!/bin/sh
refs/tags`
eval "$eval"
------------
+
+Author
+------
+Written by Junio C Hamano <gitster@pobox.com>.
+
+Documentation
+-------------
+Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
+
+GIT
+---
+Part of the linkgit:git[1] suite
--------
[verse]
'git ls-remote' [--heads] [--tags] [-u <exec> | --upload-pack <exec>]
- <repository> <refs>...
+ <repository> [<refs>...]
DESCRIPTION
-----------
-u[<mode>]::
--untracked-files[=<mode>]::
- Show untracked files (Default: 'all').
+ Show untracked files.
+
-The mode parameter is optional, and is used to specify
-the handling of untracked files. The possible options are:
+The mode parameter is optional (defaults to 'all'), and is used to
+specify the handling of untracked files; when -u is not used, the
+default is 'normal', i.e. show untracked files and directories.
++
+The possible options are:
+
---
- 'no' - Show no untracked files
- 'normal' - Shows untracked files and directories
- 'all' - Also shows individual files in untracked directories.
---
+
-See linkgit:git-config[1] for configuration variable
-used to change the default for when the option is not
-specified.
+The default can be changed using the status.showUntrackedFiles
+configuration variable documented in linkgit:git-config[1].
--ignore-submodules[=<when>]::
Ignore changes to submodules when looking for changes. <when> can be
SYNOPSIS
--------
-'git verify-pack' [-v|--verbose] [--] <pack>.idx ...
+'git verify-pack' [-v|--verbose] [-s|--stat-only] [--] <pack>.idx ...
DESCRIPTION
-n 'number'::
--max-count=<number>::
- Limit the number of commits output.
+ Limit the number of commits to output.
--skip=<number>::
char *last_elem = NULL;
struct stat st;
+ /* We've already done it */
+ if (path == buf || path == next_buf)
+ return path;
+
if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
die ("Too long path: %.*s", 60, path);
static int patch_interactive, add_interactive, edit_interactive;
static int take_worktree_changes;
-struct update_callback_data
-{
+struct update_callback_data {
int flags;
int add_errors;
};
/*
* Information on commits, used for output.
*/
-struct commit_info
-{
+struct commit_info {
const char *author;
const char *author_mail;
unsigned long author_time;
in_merge_bases(rev, &head_rev, 1) != merged) {
if (merged)
warning("deleting branch '%s' that has been merged to\n"
- " '%s', but it is not yet merged to HEAD.",
+ " '%s', but not yet been merged to HEAD.",
name, reference_name);
else
warning("not deleting branch '%s' that is not yet merged to\n"
return (is_merged == (merge_filter == SHOW_MERGED));
}
+static void add_verbose_info(struct strbuf *out, struct ref_item *item,
+ int verbose, int abbrev)
+{
+ struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
+ const char *sub = " **** invalid ref ****";
+ struct commit *commit = item->commit;
+
+ if (commit && !parse_commit(commit)) {
+ struct pretty_print_context ctx = {0};
+ pretty_print_commit(CMIT_FMT_ONELINE, commit,
+ &subject, &ctx);
+ sub = subject.buf;
+ }
+
+ if (item->kind == REF_LOCAL_BRANCH)
+ fill_tracking_info(&stat, item->name, verbose > 1);
+
+ strbuf_addf(out, " %s %s%s",
+ find_unique_abbrev(item->commit->object.sha1, abbrev),
+ stat.buf, sub);
+ strbuf_release(&stat);
+ strbuf_release(&subject);
+}
+
static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
int abbrev, int current, char *prefix)
{
if (item->dest)
strbuf_addf(&out, " -> %s", item->dest);
- else if (verbose) {
- struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
- const char *sub = " **** invalid ref ****";
-
- commit = item->commit;
- if (commit && !parse_commit(commit)) {
- struct pretty_print_context ctx = {0};
- pretty_print_commit(CMIT_FMT_ONELINE, commit,
- &subject, &ctx);
- sub = subject.buf;
- }
-
- if (item->kind == REF_LOCAL_BRANCH)
- fill_tracking_info(&stat, item->name, verbose > 1);
-
- strbuf_addf(&out, " %s %s%s",
- find_unique_abbrev(item->commit->object.sha1, abbrev),
- stat.buf, sub);
- strbuf_release(&stat);
- strbuf_release(&subject);
- }
+ else if (verbose)
+ /* " f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h" */
+ add_verbose_info(&out, item, verbose, abbrev);
printf("%s\n", out.buf);
strbuf_release(&name);
strbuf_release(&out);
* threads. The producer adds struct work_items to 'todo' and the
* consumers pick work items from the same array.
*/
-struct work_item
-{
+struct work_item {
enum work_type type;
char *name;
static const char index_pack_usage[] =
"git index-pack [-v] [-o <index-file>] [ --keep | --keep=<msg> ] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
-struct object_entry
-{
+struct object_entry {
struct pack_idx_entry idx;
unsigned long size;
unsigned int hdr_size;
#define FLAG_LINK (1u<<20)
#define FLAG_CHECKED (1u<<21)
-struct delta_entry
-{
+struct delta_entry {
union delta_base base;
int obj_no;
};
is_bare_repository_cfg = guess_repository_type(git_dir);
if (!is_bare_repository_cfg) {
- if (git_dir) {
- const char *git_dir_parent = strrchr(git_dir, '/');
- if (git_dir_parent) {
- char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
- git_work_tree_cfg = xstrdup(make_absolute_path(rel));
- free(rel);
- }
+ const char *git_dir_parent = strrchr(git_dir, '/');
+ if (git_dir_parent) {
+ char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
+ git_work_tree_cfg = xstrdup(make_absolute_path(rel));
+ free(rel);
}
if (!git_work_tree_cfg) {
git_work_tree_cfg = xcalloc(PATH_MAX, 1);
NULL
};
+static void print_commit(char sign, struct commit *commit, int verbose,
+ int abbrev)
+{
+ if (!verbose) {
+ printf("%c %s\n", sign,
+ find_unique_abbrev(commit->object.sha1, abbrev));
+ } else {
+ struct strbuf buf = STRBUF_INIT;
+ struct pretty_print_context ctx = {0};
+ pretty_print_commit(CMIT_FMT_ONELINE, commit, &buf, &ctx);
+ printf("%c %s %s\n", sign,
+ find_unique_abbrev(commit->object.sha1, abbrev),
+ buf.buf);
+ strbuf_release(&buf);
+ }
+}
+
int cmd_cherry(int argc, const char **argv, const char *prefix)
{
struct rev_info revs;
commit = list->item;
if (has_commit_patch_id(commit, &ids))
sign = '-';
-
- if (verbose) {
- struct strbuf buf = STRBUF_INIT;
- struct pretty_print_context ctx = {0};
- pretty_print_commit(CMIT_FMT_ONELINE, commit,
- &buf, &ctx);
- printf("%c %s %s\n", sign,
- find_unique_abbrev(commit->object.sha1, abbrev),
- buf.buf);
- strbuf_release(&buf);
- }
- else {
- printf("%c %s\n", sign,
- find_unique_abbrev(commit->object.sha1, abbrev));
- }
-
+ print_commit(sign, commit, verbose, abbrev);
list = list->next;
}
}
+static void write_merge_msg(void)
+{
+ int fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666);
+ if (fd < 0)
+ die_errno("Could not open '%s' for writing",
+ git_path("MERGE_MSG"));
+ if (write_in_full(fd, merge_msg.buf, merge_msg.len) != merge_msg.len)
+ die_errno("Could not write to '%s'", git_path("MERGE_MSG"));
+ close(fd);
+}
+
+static void read_merge_msg(void)
+{
+ strbuf_reset(&merge_msg);
+ if (strbuf_read_file(&merge_msg, git_path("MERGE_MSG"), 0) < 0)
+ die_errno("Could not read from '%s'", git_path("MERGE_MSG"));
+}
+
+static void run_prepare_commit_msg(void)
+{
+ write_merge_msg();
+ run_hook(get_index_file(), "prepare-commit-msg",
+ git_path("MERGE_MSG"), "merge", NULL, NULL);
+ read_merge_msg();
+}
+
static int merge_trivial(void)
{
unsigned char result_tree[20], result_commit[20];
parent->next = xmalloc(sizeof(*parent->next));
parent->next->item = remoteheads->item;
parent->next->next = NULL;
+ run_prepare_commit_msg();
commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL);
finish(result_commit, "In-index merge");
drop_save();
}
free_commit_list(remoteheads);
strbuf_addch(&merge_msg, '\n');
+ run_prepare_commit_msg();
commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL);
strbuf_addf(&buf, "Merge made by %s.", wt_strategy);
finish(result_commit, buf.buf);
die_errno("Could not write to '%s'", git_path("MERGE_HEAD"));
close(fd);
strbuf_addch(&merge_msg, '\n');
- fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666);
- if (fd < 0)
- die_errno("Could not open '%s' for writing",
- git_path("MERGE_MSG"));
- if (write_in_full(fd, merge_msg.buf, merge_msg.len) !=
- merge_msg.len)
- die_errno("Could not write to '%s'", git_path("MERGE_MSG"));
- close(fd);
+ write_merge_msg();
fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0)
die_errno("Could not open '%s' for writing",
p += 7;
else if (!memcmp(line, "From ", 5))
p += 5;
+ else if (!memcmp(line, "\\ ", 2) && 12 < strlen(line))
+ continue;
if (!get_sha1_hex(p, next_sha1)) {
found_next = 1;
extern int prefer_symlink_refs;
extern int log_all_ref_updates;
extern int warn_ambiguous_refs;
-extern int unique_abbrev_extra_length;
extern int shared_repository;
extern const char *apply_default_whitespace;
extern const char *apply_default_ignorewhitespace;
enum auto_crlf {
AUTO_CRLF_FALSE = 0,
AUTO_CRLF_TRUE = 1,
- AUTO_CRLF_INPUT = -1,
+ AUTO_CRLF_INPUT = -1
};
extern enum auto_crlf auto_crlf;
CMIT_FMT_UNSPECIFIED
};
-struct pretty_print_context
-{
+struct pretty_print_context {
int abbrev;
const char *subject;
const char *after_subject;
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-#define bswap32(x) ({ \
- uint32_t __res; \
- if (__builtin_constant_p(x)) { \
- __res = default_swab32(x); \
- } else { \
- __asm__("bswap %0" : "=r" (__res) : "0" ((uint32_t)(x))); \
- } \
- __res; })
+#define bswap32 git_bswap32
+static inline uint32_t git_bswap32(uint32_t x)
+{
+ uint32_t result;
+ if (__builtin_constant_p(x))
+ result = default_swab32(x);
+ else
+ __asm__("bswap %0" : "=r" (result) : "0" (x));
+ return result;
+}
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
const char *config_exclusive_filename = NULL;
-struct config_item
-{
+struct config_item {
struct config_item *next;
char *name;
char *value;
return 0;
}
- if (!strcmp(var, "core.abbrevguard")) {
- unique_abbrev_extra_length = git_config_int(var, value);
- if (unique_abbrev_extra_length < 0)
- unique_abbrev_extra_length = 0;
- return 0;
- }
-
if (!strcmp(var, "core.bare")) {
is_bare_repository_cfg = git_config_bool(var, value);
return 0;
CRLF_TEXT,
CRLF_INPUT,
CRLF_CRLF,
- CRLF_AUTO,
+ CRLF_AUTO
};
struct text_stat {
buffer->text.ptr[buffer->text.size] = '\0';
}
-struct diff_words_style_elem
-{
+struct diff_words_style_elem {
const char *prefix;
const char *suffix;
const char *color; /* NULL; filled in by the setup code if
* color is enabled */
};
-struct diff_words_style
-{
+struct diff_words_style {
enum diff_words_type type;
struct diff_words_style_elem new, old, ctx;
const char *newline;
int is_bare_repository_cfg = -1; /* unspecified */
int log_all_ref_updates = -1; /* unspecified */
int warn_ambiguous_refs = 1;
-int unique_abbrev_extra_length;
int repository_format_version;
const char *git_commit_encoding;
const char *git_log_output_encoding;
#define DEPTH_BITS 13
#define MAX_DEPTH ((1<<DEPTH_BITS)-1)
-struct object_entry
-{
+struct object_entry {
struct pack_idx_entry idx;
struct object_entry *next;
uint32_t type : TYPE_BITS,
depth : DEPTH_BITS;
};
-struct object_entry_pool
-{
+struct object_entry_pool {
struct object_entry_pool *next_pool;
struct object_entry *next_free;
struct object_entry *end;
struct object_entry entries[FLEX_ARRAY]; /* more */
};
-struct mark_set
-{
+struct mark_set {
union {
struct object_entry *marked[1024];
struct mark_set *sets[1024];
unsigned int shift;
};
-struct last_object
-{
+struct last_object {
struct strbuf data;
off_t offset;
unsigned int depth;
unsigned no_swap : 1;
};
-struct mem_pool
-{
+struct mem_pool {
struct mem_pool *next_pool;
char *next_free;
char *end;
uintmax_t space[FLEX_ARRAY]; /* more */
};
-struct atom_str
-{
+struct atom_str {
struct atom_str *next_atom;
unsigned short str_len;
char str_dat[FLEX_ARRAY]; /* more */
};
struct tree_content;
-struct tree_entry
-{
+struct tree_entry {
struct tree_content *tree;
struct atom_str *name;
- struct tree_entry_ms
- {
+ struct tree_entry_ms {
uint16_t mode;
unsigned char sha1[20];
} versions[2];
};
-struct tree_content
-{
+struct tree_content {
unsigned int entry_capacity; /* must match avail_tree_content */
unsigned int entry_count;
unsigned int delta_depth;
struct tree_entry *entries[FLEX_ARRAY]; /* more */
};
-struct avail_tree_content
-{
+struct avail_tree_content {
unsigned int entry_capacity; /* must match tree_content */
struct avail_tree_content *next_avail;
};
-struct branch
-{
+struct branch {
struct branch *table_next_branch;
struct branch *active_next_branch;
const char *name;
unsigned char sha1[20];
};
-struct tag
-{
+struct tag {
struct tag *next_tag;
const char *name;
unsigned int pack_id;
unsigned char sha1[20];
};
-struct hash_list
-{
+struct hash_list {
struct hash_list *next;
unsigned char sha1[20];
};
WHENSPEC_NOW
} whenspec_type;
-struct recent_command
-{
+struct recent_command {
struct recent_command *prev;
struct recent_command *next;
char *buf;
#ifndef FETCH_PACK_H
#define FETCH_PACK_H
-struct fetch_pack_args
-{
+struct fetch_pack_args {
const char *uploadpack;
int unpacklimit;
int depth;
#!/bin/sh
echo "/* Automatically generated by $0 */
-struct cmdname_help
-{
+struct cmdname_help {
char name[16];
char help[80];
};
close $fd;
open $fd, quote_command(git_cmd(), "cat-file", "blob", $hash)." | ".
quote_command($highlight_bin).
- " --fragment --syntax $syntax |"
+ " --replace-tabs=8 --fragment --syntax $syntax |"
or die_error(500, "Couldn't open file or run syntax highlighter");
return $fd;
}
$href_params{'-title'} = 'log';
}
- foreach my $format qw(RSS Atom) {
+ foreach my $format (qw(RSS Atom)) {
my $type = lc($format);
my %link_attr = (
'-rel' => 'alternate',
}
$href_params{'-title'} ||= 'log';
- foreach my $format qw(RSS Atom) {
+ foreach my $format (qw(RSS Atom)) {
$href_params{'action'} = lc($format);
print $cgi->a({-href => href(%href_params),
-title => "$href_params{'-title'} $format feed",
}
if ($diff->{'from_mode'} ne ('0' x 6)) {
$from_mode_oct = oct $diff->{'from_mode'};
- if (S_ISREG($to_mode_oct)) { # only for regular file
+ if (S_ISREG($from_mode_oct)) { # only for regular file
$from_mode_str = sprintf("%04o", $from_mode_oct & 0777); # permission bits
}
$from_file_type = file_type($diff->{'from_mode'});
static struct object_list *objects;
-struct repo
-{
+struct repo {
char *url;
char *path;
int path_len;
COMPLETE
};
-struct transfer_request
-{
+struct transfer_request {
struct object *obj;
char *url;
char *dest;
static struct transfer_request *request_queue_head;
-struct xml_ctx
-{
+struct xml_ctx {
char *name;
int len;
char *cdata;
void *userData;
};
-struct remote_lock
-{
+struct remote_lock {
char *url;
char *owner;
char *token;
/* Flags that remote_ls passes to callback functions */
#define IS_DIR (1u << 0)
-struct remote_ls_ctx
-{
+struct remote_ls_ctx {
char *path;
void (*userFunc)(struct remote_ls_ctx *ls);
void *userData;
#include "walker.h"
#include "http.h"
-struct alt_base
-{
+struct alt_base {
char *base;
int got_indices;
struct packed_git *packs;
COMPLETE
};
-struct object_request
-{
+struct object_request {
struct walker *walker;
unsigned char sha1[20];
struct alt_base *repo;
#define NO_CURL_IOCTL
#endif
-struct slot_results
-{
+struct slot_results {
CURLcode curl_result;
long http_code;
};
-struct active_request_slot
-{
+struct active_request_slot {
CURL *curl;
FILE *local;
int in_use;
struct active_request_slot *next;
};
-struct buffer
-{
+struct buffer {
struct strbuf buf;
size_t posn;
};
extern int http_get_info_packs(const char *base_url,
struct packed_git **packs_head);
-struct http_pack_request
-{
+struct http_pack_request {
char *url;
struct packed_git *target;
struct packed_git **lst;
extern void release_http_pack_request(struct http_pack_request *preq);
/* Helpers for fetching object */
-struct http_object_request
-{
+struct http_object_request {
char *url;
char tmpfile[PATH_MAX];
int localfile;
* Since we want to write the index eventually, we cannot reuse the index
* for these (temporary) data.
*/
-struct stage_data
-{
- struct
- {
+struct stage_data {
+ struct {
unsigned mode;
unsigned char sha[20];
} stages[4];
}
}
-struct rename
-{
+struct rename {
struct diff_filepair *pair;
struct stage_data *src_entry;
struct stage_data *dst_entry;
/* Low level file merging, update and removal */
-struct merge_file_info
-{
+struct merge_file_info {
unsigned char sha[20];
unsigned mode;
unsigned clean:1,
#include "pack.h"
#include "pack-revindex.h"
-struct idx_entry
-{
+struct idx_entry {
off_t offset;
const unsigned char *sha1;
unsigned int nr;
if (exists
? !status
: status == SHORT_NAME_NOT_FOUND) {
- int cut_at = len + unique_abbrev_extra_length;
- cut_at = (cut_at < 40) ? cut_at : 40;
- hex[cut_at] = 0;
+ hex[len] = 0;
return hex;
}
len++;
char *string;
void *util;
};
-struct string_list
-{
+struct string_list {
struct string_list_item *items;
unsigned int nr, alloc;
unsigned int strdup_strings:1;
die("bad --ignore-submodules argument: %s", arg);
}
+static int prepare_submodule_summary(struct rev_info *rev, const char *path,
+ struct commit *left, struct commit *right,
+ int *fast_forward, int *fast_backward)
+{
+ struct commit_list *merge_bases, *list;
+
+ init_revisions(rev, NULL);
+ setup_revisions(0, NULL, rev, NULL);
+ rev->left_right = 1;
+ rev->first_parent_only = 1;
+ left->object.flags |= SYMMETRIC_LEFT;
+ add_pending_object(rev, &left->object, path);
+ add_pending_object(rev, &right->object, path);
+ merge_bases = get_merge_bases(left, right, 1);
+ if (merge_bases) {
+ if (merge_bases->item == left)
+ *fast_forward = 1;
+ else if (merge_bases->item == right)
+ *fast_backward = 1;
+ }
+ for (list = merge_bases; list; list = list->next) {
+ list->item->object.flags |= UNINTERESTING;
+ add_pending_object(rev, &list->item->object,
+ sha1_to_hex(list->item->object.sha1));
+ }
+ return prepare_revision_walk(rev);
+}
+
+static void print_submodule_summary(struct rev_info *rev, FILE *f,
+ const char *del, const char *add, const char *reset)
+{
+ static const char format[] = " %m %s";
+ struct strbuf sb = STRBUF_INIT;
+ struct commit *commit;
+
+ while ((commit = get_revision(rev))) {
+ struct pretty_print_context ctx = {0};
+ ctx.date_mode = rev->date_mode;
+ strbuf_setlen(&sb, 0);
+ if (commit->object.flags & SYMMETRIC_LEFT) {
+ if (del)
+ strbuf_addstr(&sb, del);
+ }
+ else if (add)
+ strbuf_addstr(&sb, add);
+ format_commit_message(commit, format, &sb, &ctx);
+ if (reset)
+ strbuf_addstr(&sb, reset);
+ strbuf_addch(&sb, '\n');
+ fprintf(f, "%s", sb.buf);
+ }
+ strbuf_release(&sb);
+}
+
void show_submodule_summary(FILE *f, const char *path,
unsigned char one[20], unsigned char two[20],
unsigned dirty_submodule,
const char *del, const char *add, const char *reset)
{
struct rev_info rev;
- struct commit *commit, *left = left, *right = right;
- struct commit_list *merge_bases, *list;
+ struct commit *left = left, *right = right;
const char *message = NULL;
struct strbuf sb = STRBUF_INIT;
- static const char *format = " %m %s";
int fast_forward = 0, fast_backward = 0;
if (is_null_sha1(two))
!(right = lookup_commit_reference(two)))
message = "(commits not present)";
- if (!message) {
- init_revisions(&rev, NULL);
- setup_revisions(0, NULL, &rev, NULL);
- rev.left_right = 1;
- rev.first_parent_only = 1;
- left->object.flags |= SYMMETRIC_LEFT;
- add_pending_object(&rev, &left->object, path);
- add_pending_object(&rev, &right->object, path);
- merge_bases = get_merge_bases(left, right, 1);
- if (merge_bases) {
- if (merge_bases->item == left)
- fast_forward = 1;
- else if (merge_bases->item == right)
- fast_backward = 1;
- }
- for (list = merge_bases; list; list = list->next) {
- list->item->object.flags |= UNINTERESTING;
- add_pending_object(&rev, &list->item->object,
- sha1_to_hex(list->item->object.sha1));
- }
- if (prepare_revision_walk(&rev))
- message = "(revision walker failed)";
- }
+ if (!message &&
+ prepare_submodule_summary(&rev, path, left, right,
+ &fast_forward, &fast_backward))
+ message = "(revision walker failed)";
if (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
fprintf(f, "Submodule %s contains untracked content\n", path);
fwrite(sb.buf, sb.len, 1, f);
if (!message) {
- while ((commit = get_revision(&rev))) {
- struct pretty_print_context ctx = {0};
- ctx.date_mode = rev.date_mode;
- strbuf_setlen(&sb, 0);
- if (commit->object.flags & SYMMETRIC_LEFT) {
- if (del)
- strbuf_addstr(&sb, del);
- }
- else if (add)
- strbuf_addstr(&sb, add);
- format_commit_message(commit, format, &sb, &ctx);
- if (reset)
- strbuf_addstr(&sb, reset);
- strbuf_addch(&sb, '\n');
- fprintf(f, "%s", sb.buf);
- }
+ print_submodule_summary(&rev, f, del, add, reset);
clear_commit_marks(left, ~0);
clear_commit_marks(right, ~0);
}
+
strbuf_release(&sb);
}
Skipping tests
--------------
-If you need to skip tests you should do so be using the three-arg form
+If you need to skip tests you should do so by using the three-arg form
of the test_* functions (see the "Test harness library" section
below), e.g.:
}
close O;
' gitweb.output &&
- if grep '^[[]' gitweb.log >/dev/null 2>&1; then false; else true; fi
+ if grep '^[[]' gitweb.log >/dev/null 2>&1; then
+ test_debug 'cat gitweb.log >&2' &&
+ false
+ else
+ true
+ fi
# gitweb.log is left for debugging
# gitweb.output is used to parse HTTP output
test_cmp patch-id_master patch-id_same
'
+cat >nonl <<\EOF
+diff --git i/a w/a
+index e69de29..2e65efe 100644
+--- i/a
++++ w/a
+@@ -0,0 +1 @@
++a
+\ No newline at end of file
+diff --git i/b w/b
+index e69de29..6178079 100644
+--- i/b
++++ w/b
+@@ -0,0 +1 @@
++b
+EOF
+
+cat >withnl <<\EOF
+diff --git i/a w/a
+index e69de29..7898192 100644
+--- i/a
++++ w/a
+@@ -0,0 +1 @@
++a
+diff --git i/b w/b
+index e69de29..6178079 100644
+--- i/b
++++ w/b
+@@ -0,0 +1 @@
++b
+EOF
+
+test_expect_success 'patch-id handles no-nl-at-eof markers' '
+ cat nonl | calc_patch_id nonl &&
+ cat withnl | calc_patch_id withnl &&
+ test_cmp patch-id_nonl patch-id_withnl
+'
test_done
. ./test-lib.sh
commit_msg_is () {
- test "`git log --pretty=format:%s%b -1`" = "$1"
+ expect=commit_msg_is.expect
+ actual=commit_msg_is.actual
+
+ printf "%s" "$(git log --pretty=format:%s%b -1)" >$expect &&
+ printf "%s" "$1" >$actual &&
+ test_cmp $expect $actual
}
# A sanity check to see if commit is working at all.
'
+test_expect_success 'with hook (merge)' '
+
+ head=`git rev-parse HEAD` &&
+ git checkout -b other HEAD@{1} &&
+ echo "more" >> file &&
+ git add file &&
+ git commit -m other &&
+ git checkout - &&
+ git merge other &&
+ test "`git log -1 --pretty=format:%s`" = merge
+'
+
cat > "$HOOK" <<'EOF'
#!/bin/sh
exit 1
test_expect_success \
'no commits: projects_list (implicit)' \
'gitweb_run'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: projects_index' \
'gitweb_run "a=project_index"'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: .git summary (implicit)' \
'gitweb_run "p=.git"'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: .git commit (implicit HEAD)' \
'gitweb_run "p=.git;a=commit"'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: .git commitdiff (implicit HEAD)' \
'gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: .git tree (implicit HEAD)' \
'gitweb_run "p=.git;a=tree"'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: .git heads' \
'gitweb_run "p=.git;a=heads"'
-test_debug 'cat gitweb.log'
test_expect_success \
'no commits: .git tags' \
'gitweb_run "p=.git;a=tags"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
test_expect_success \
'projects_list (implicit)' \
'gitweb_run'
-test_debug 'cat gitweb.log'
test_expect_success \
'projects_index' \
'gitweb_run "a=project_index"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git summary (implicit)' \
'gitweb_run "p=.git"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git commit (implicit HEAD)' \
'gitweb_run "p=.git;a=commit"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git commitdiff (implicit HEAD, root commit)' \
'gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git commitdiff_plain (implicit HEAD, root commit)' \
'gitweb_run "p=.git;a=commitdiff_plain"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git commit (HEAD)' \
'gitweb_run "p=.git;a=commit;h=HEAD"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git tree (implicit HEAD)' \
'gitweb_run "p=.git;a=tree"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git blob (file)' \
'gitweb_run "p=.git;a=blob;f=file"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git blob_plain (file)' \
'gitweb_run "p=.git;a=blob_plain;f=file"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# nonexistent objects
test_expect_success \
'.git commit (non-existent)' \
'gitweb_run "p=.git;a=commit;h=non-existent"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git commitdiff (non-existent)' \
'gitweb_run "p=.git;a=commitdiff;h=non-existent"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git commitdiff (non-existent vs HEAD)' \
'gitweb_run "p=.git;a=commitdiff;hp=non-existent;h=HEAD"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git tree (0000000000000000000000000000000000000000)' \
'gitweb_run "p=.git;a=tree;h=0000000000000000000000000000000000000000"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git tag (0000000000000000000000000000000000000000)' \
'gitweb_run "p=.git;a=tag;h=0000000000000000000000000000000000000000"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git blob (non-existent)' \
'gitweb_run "p=.git;a=blob;f=non-existent"'
-test_debug 'cat gitweb.log'
test_expect_success \
'.git blob_plain (non-existent)' \
'gitweb_run "p=.git;a=blob_plain;f=non-existent"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
test_expect_success \
'commitdiff(0): root' \
'gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): file added' \
git add new_file &&
git commit -a -m "File added." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): mode change' \
'test_chmod +x new_file &&
git commit -a -m "Mode changed." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): file renamed' \
'git mv new_file renamed_file &&
git commit -a -m "File renamed." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success SYMLINKS \
'commitdiff(0): file to symlink' \
ln -s file renamed_file &&
git commit -a -m "File to symlink." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): file deleted' \
rm -f renamed_file &&
git commit -a -m "File removed." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): file copied / new file' \
git add file2 &&
git commit -a -m "File copied." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): mode change and modified' \
test_chmod +x file2 &&
git commit -a -m "Mode change and modification." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): renamed and modified' \
echo "Propter nomen suum." >> file3 &&
git commit -a -m "File rename and modification." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): renamed, mode change and modified' \
test_chmod +x file2 &&
git commit -a -m "File rename, mode change and modification." &&
gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# commitdiff testing (taken from t4114-apply-typechange.sh)
test_expect_success \
'commitdiff(2): file renamed from foo to foo/baz' \
'gitweb_run "p=.git;a=commitdiff;hp=initial;h=foo-baz-renamed-from-foo"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): file renamed from foo/baz to foo' \
'gitweb_run "p=.git;a=commitdiff;hp=foo-baz-renamed-from-foo;h=initial"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): directory becomes file' \
'gitweb_run "p=.git;a=commitdiff;hp=foo-becomes-a-directory;h=initial"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): file becomes directory' \
'gitweb_run "p=.git;a=commitdiff;hp=initial;h=foo-becomes-a-directory"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): file becomes symlink' \
'gitweb_run "p=.git;a=commitdiff;hp=initial;h=foo-symlinked-to-bar"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): symlink becomes file' \
'gitweb_run "p=.git;a=commitdiff;hp=foo-symlinked-to-bar;h=foo-back-to-file"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): symlink becomes directory' \
'gitweb_run "p=.git;a=commitdiff;hp=foo-symlinked-to-bar;h=foo-becomes-a-directory"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(2): directory becomes symlink' \
'gitweb_run "p=.git;a=commitdiff;hp=foo-becomes-a-directory;h=foo-symlinked-to-bar"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# commit, commitdiff: merge, large
test_expect_success \
'commit(0): merge commit' \
'gitweb_run "p=.git;a=commit"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(0): merge commit' \
'gitweb_run "p=.git;a=commitdiff"'
-test_debug 'cat gitweb.log'
test_expect_success \
'Prepare large commit' \
test_expect_success \
'commit(1): large commit' \
'gitweb_run "p=.git;a=commit;h=b"'
-test_debug 'cat gitweb.log'
test_expect_success \
'commitdiff(1): large commit' \
'gitweb_run "p=.git;a=commitdiff;h=b"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# tags testing
git tag lightweight/tag-tree HEAD^{tree} &&
git tag lightweight/tag-blob HEAD:file &&
gitweb_run "p=.git;a=tags"'
-test_debug 'cat gitweb.log'
test_expect_success \
'tag: Tag to commit object' \
'gitweb_run "p=.git;a=tag;h=tag-commit"'
-test_debug 'cat gitweb.log'
test_expect_success \
'tag: on lightweight tag (invalid)' \
'gitweb_run "p=.git;a=tag;h=lightweight/tag-commit"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# logs
test_expect_success \
'logs: log (implicit HEAD)' \
'gitweb_run "p=.git;a=log"'
-test_debug 'cat gitweb.log'
test_expect_success \
'logs: shortlog (implicit HEAD)' \
'gitweb_run "p=.git;a=shortlog"'
-test_debug 'cat gitweb.log'
test_expect_success \
'logs: history (implicit HEAD, file)' \
'gitweb_run "p=.git;a=history;f=file"'
-test_debug 'cat gitweb.log'
test_expect_success \
'logs: history (implicit HEAD, non-existent file)' \
'gitweb_run "p=.git;a=history;f=non-existent"'
-test_debug 'cat gitweb.log'
test_expect_success \
'logs: history (implicit HEAD, deleted file)' \
git rm deleted_file &&
git commit -m "Delete file" &&
gitweb_run "p=.git;a=history;f=deleted_file"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# path_info links
test_expect_success \
'path_info: project' \
'gitweb_run "" "/.git"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/branch' \
'gitweb_run "" "/.git/b"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/branch:file' \
'gitweb_run "" "/.git/master:file"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/branch:dir/' \
'gitweb_run "" "/.git/master:foo/"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/branch:file (non-existent)' \
'gitweb_run "" "/.git/master:non-existent"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/branch:dir/ (non-existent)' \
'gitweb_run "" "/.git/master:non-existent/"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/branch:/file' \
'gitweb_run "" "/.git/master:/file"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/:/file (implicit HEAD)' \
'gitweb_run "" "/.git/:/file"'
-test_debug 'cat gitweb.log'
test_expect_success \
'path_info: project/:/ (implicit HEAD, top tree)' \
'gitweb_run "" "/.git/:/"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
test_expect_success \
'feeds: OPML' \
'gitweb_run "a=opml"'
-test_debug 'cat gitweb.log'
test_expect_success \
'feed: RSS' \
'gitweb_run "p=.git;a=rss"'
-test_debug 'cat gitweb.log'
test_expect_success \
'feed: Atom' \
'gitweb_run "p=.git;a=atom"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# encoding/decoding
git add file &&
git commit -F "$TEST_DIRECTORY"/t3900/1-UTF-8.txt &&
gitweb_run "p=.git;a=commit"'
-test_debug 'cat gitweb.log'
test_expect_success \
'encode(commit): iso-8859-1' \
git commit -F "$TEST_DIRECTORY"/t3900/ISO8859-1.txt &&
git config --unset i18n.commitencoding &&
gitweb_run "p=.git;a=commit"'
-test_debug 'cat gitweb.log'
test_expect_success \
'encode(log): utf-8 and iso-8859-1' \
'gitweb_run "p=.git;a=log"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# extra options
test_expect_success \
'opt: log --no-merges' \
'gitweb_run "p=.git;a=log;opt=--no-merges"'
-test_debug 'cat gitweb.log'
test_expect_success \
'opt: atom --no-merges' \
'gitweb_run "p=.git;a=log;opt=--no-merges"'
-test_debug 'cat gitweb.log'
test_expect_success \
'opt: "file" history --no-merges' \
'gitweb_run "p=.git;a=history;f=file;opt=--no-merges"'
-test_debug 'cat gitweb.log'
test_expect_success \
'opt: log --no-such-option (invalid option)' \
'gitweb_run "p=.git;a=log;opt=--no-such-option"'
-test_debug 'cat gitweb.log'
test_expect_success \
'opt: tree --no-merges (invalid option for action)' \
'gitweb_run "p=.git;a=tree;opt=--no-merges"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# testing config_to_multi / cloneurl
test_expect_success \
'URL: no project URLs, no base URL' \
'gitweb_run "p=.git;a=summary"'
-test_debug 'cat gitweb.log'
test_expect_success \
'URL: project URLs via gitweb.url' \
'git config --add gitweb.url git://example.com/git/trash.git &&
git config --add gitweb.url http://example.com/git/trash.git &&
gitweb_run "p=.git;a=summary"'
-test_debug 'cat gitweb.log'
cat >.git/cloneurl <<\EOF
git://example.com/git/trash.git
test_expect_success \
'URL: project URLs via cloneurl file' \
'gitweb_run "p=.git;a=summary"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# gitweb config and repo config
test_expect_success \
'config override: projects list (implicit)' \
'gitweb_run'
-test_debug 'cat gitweb.log'
test_expect_success \
'config override: tree view, features not overridden in repo config' \
'gitweb_run "p=.git;a=tree"'
-test_debug 'cat gitweb.log'
test_expect_success \
'config override: tree view, features disabled in repo config' \
git config gitweb.snapshot none &&
git config gitweb.avatar gravatar &&
gitweb_run "p=.git;a=tree"'
-test_debug 'cat gitweb.log'
test_expect_success \
'config override: tree view, features enabled in repo config (1)' \
'git config gitweb.blame yes &&
git config gitweb.snapshot "zip,tgz, tbz2" &&
gitweb_run "p=.git;a=tree"'
-test_debug 'cat gitweb.log'
cat >.git/config <<\EOF
# testing noval and alternate separator
test_expect_success \
'config override: tree view, features enabled in repo config (2)' \
'gitweb_run "p=.git;a=tree"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# non-ASCII in README.html
'echo "<b>UTF-8 example:</b><br />" > .git/README.html &&
cat "$TEST_DIRECTORY"/t3900/1-UTF-8.txt >> .git/README.html &&
gitweb_run "p=.git;a=summary"'
-test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# syntax highlighting
'syntax highlighting (no highlight, unknown syntax)' \
'git config gitweb.highlight yes &&
gitweb_run "p=.git;a=blob;f=file"'
-test_debug 'cat gitweb.log'
test_expect_success HIGHLIGHT \
'syntax highlighting (highlighted, shell script)' \
git add test.sh &&
git commit -m "Add test.sh" &&
gitweb_run "p=.git;a=blob;f=test.sh"'
-test_debug 'cat gitweb.log'
test_done
grep "Status: 503 Service Unavailable" gitweb.headers &&
grep "503 - The load average on the server is too high" gitweb.body
'
-test_debug 'cat gitweb.log' # just in case
test_debug 'cat gitweb.headers'
# turn off load checking
fun:write_buffer
fun:write_loose_object
}
+
+{
+ ignore-sse-strlen-invalid-read-size
+ Memcheck:Addr4
+ fun:copy_ref
+}
item->tagged = NULL;
}
- if (prefixcmp(bufptr, "tag "))
+ if (bufptr + 4 < tail && !prefixcmp(bufptr, "tag "))
+ ; /* good */
+ else
return -1;
bufptr += 4;
nl = memchr(bufptr, '\n', tail - bufptr);
item->tag = xmemdupz(bufptr, nl - bufptr);
bufptr = nl + 1;
- if (!prefixcmp(bufptr, "tagger "))
+ if (bufptr + 7 < tail && !prefixcmp(bufptr, "tagger "))
item->date = parse_tag_date(bufptr, tail);
else
item->date = 0;
static int debug;
-struct helper_data
-{
+struct helper_data {
const char *name;
struct child_process *helper;
FILE *out;