author | Junio C Hamano <gitster@pobox.com> | |
Sun, 3 Apr 2011 19:33:05 +0000 (12:33 -0700) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Sun, 3 Apr 2011 19:33:05 +0000 (12:33 -0700) |
* jc/index-update-if-able:
update $GIT_INDEX_FILE when there are racily clean entries
diff/status: refactor opportunistic index update
update $GIT_INDEX_FILE when there are racily clean entries
diff/status: refactor opportunistic index update
1 | 2 | |||
---|---|---|---|---|
builtin/commit.c | patch | | diff1 | | diff2 | | blob | history |
builtin/diff.c | patch | | diff1 | | diff2 | | blob | history |
cache.h | patch | | diff1 | | diff2 | | blob | history |
read-cache.c | patch | | diff1 | | diff2 | | blob | history |
diff --combined builtin/commit.c
index d71e1e0c9c27c4d03cd02b4deaacec67af33917a,0b6ce2fa3757b0d052ee28d716687a70e1c4ca37..6e32166a297d2e8783e9a24dee6398bb0aa28e98
--- 1/builtin/commit.c
--- 2/builtin/commit.c
+++ b/builtin/commit.c
" git config --global user.name \"Your Name\"\n"
" git config --global user.email you@example.com\n"
"\n"
-"If the identity used for this commit is wrong, you can fix it with:\n"
+"After doing this, you may fix the identity used for this commit with:\n"
"\n"
-" git commit --amend --author='Your Name <you@example.com>'\n";
+" git commit --amend --reset-author\n";
static const char empty_amend_advice[] =
"You asked to amend the most recent commit, but doing so would make\n"
static const char *logfile, *force_author;
static const char *template_file;
static char *edit_message, *use_message;
-static char *author_name, *author_email, *author_date;
+static char *fixup_message, *squash_message;
static int all, edit_flag, also, interactive, only, amend, signoff;
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
static int no_post_rewrite, allow_empty_message;
}
static struct option builtin_commit_options[] = {
- OPT__QUIET(&quiet),
- OPT__VERBOSE(&verbose),
+ OPT__QUIET(&quiet, "suppress summary after successful commit"),
+ OPT__VERBOSE(&verbose, "show diff in commit message template"),
OPT_GROUP("Commit message options"),
- OPT_FILENAME('F', "file", &logfile, "read log from file"),
- OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
- OPT_STRING(0, "date", &force_date, "DATE", "override date for commit"),
- OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m),
- OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit"),
- OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
+ OPT_FILENAME('F', "file", &logfile, "read message from file"),
+ OPT_STRING(0, "author", &force_author, "author", "override author for commit"),
+ OPT_STRING(0, "date", &force_date, "date", "override date for commit"),
+ OPT_CALLBACK('m', "message", &message, "message", "commit message", opt_parse_m),
+ OPT_STRING('c', "reedit-message", &edit_message, "commit", "reuse and edit message from specified commit"),
+ OPT_STRING('C', "reuse-message", &use_message, "commit", "reuse message from specified commit"),
+ OPT_STRING(0, "fixup", &fixup_message, "commit", "use autosquash formatted message to fixup specified commit"),
+ OPT_STRING(0, "squash", &squash_message, "commit", "use autosquash formatted message to squash specified commit"),
OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"),
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
OPT_FILENAME('t', "template", &template_file, "use specified template file"),
STATUS_FORMAT_SHORT),
OPT_BOOLEAN(0, "branch", &status_show_branch, "show branch information"),
OPT_SET_INT(0, "porcelain", &status_format,
- "show porcelain output format", STATUS_FORMAT_PORCELAIN),
+ "machine-readable output", STATUS_FORMAT_PORCELAIN),
OPT_BOOLEAN('z', "null", &null_termination,
"terminate entries with NUL"),
OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, "bypass post-rewrite hook"),
- { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
+ { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
/* end commit contents options */
{ OPTION_BOOLEAN, 0, "allow-empty", &allow_empty, NULL,
static const char sign_off_header[] = "Signed-off-by: ";
-static void determine_author_info(void)
+static void determine_author_info(struct strbuf *author_ident)
{
char *name, *email, *date;
if (force_date)
date = force_date;
-
- author_name = name;
- author_email = email;
- author_date = date;
+ strbuf_addstr(author_ident, fmt_ident(name, email, date,
+ IDENT_ERROR_ON_NO_NAME));
}
static int ends_rfc2822_footer(struct strbuf *sb)
return 1;
}
+static char *cut_ident_timestamp_part(char *string)
+{
+ char *ket = strrchr(string, '>');
+ if (!ket || ket[1] != ' ')
+ die("Malformed ident string: '%s'", string);
+ *++ket = '\0';
+ return ket;
+}
+
static int prepare_to_commit(const char *index_file, const char *prefix,
- struct wt_status *s)
+ struct wt_status *s,
+ struct strbuf *author_ident)
{
struct stat statbuf;
+ struct strbuf committer_ident = STRBUF_INIT;
int commitable, saved_color_setting;
struct strbuf sb = STRBUF_INIT;
char *buffer;
if (!no_verify && run_hook(index_file, "pre-commit", NULL))
return 0;
+ if (squash_message) {
+ /*
+ * Insert the proper subject line before other commit
+ * message options add their content.
+ */
+ if (use_message && !strcmp(use_message, squash_message))
+ strbuf_addstr(&sb, "squash! ");
+ else {
+ struct pretty_print_context ctx = {0};
+ struct commit *c;
+ c = lookup_commit_reference_by_name(squash_message);
+ if (!c)
+ die("could not lookup commit %s", squash_message);
+ ctx.output_encoding = get_commit_output_encoding();
+ format_commit_message(c, "squash! %s\n\n", &sb,
+ &ctx);
+ }
+ }
+
if (message.len) {
strbuf_addbuf(&sb, &message);
hook_arg1 = "message";
strbuf_add(&sb, buffer + 2, strlen(buffer + 2));
hook_arg1 = "commit";
hook_arg2 = use_message;
+ } else if (fixup_message) {
+ struct pretty_print_context ctx = {0};
+ struct commit *commit;
+ commit = lookup_commit_reference_by_name(fixup_message);
+ if (!commit)
+ die("could not lookup commit %s", fixup_message);
+ ctx.output_encoding = get_commit_output_encoding();
+ format_commit_message(commit, "fixup! %s\n\n",
+ &sb, &ctx);
+ hook_arg1 = "message";
} else if (!stat(git_path("MERGE_MSG"), &statbuf)) {
if (strbuf_read_file(&sb, git_path("MERGE_MSG"), 0) < 0)
die_errno("could not read MERGE_MSG");
if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0)
die_errno("could not read SQUASH_MSG");
hook_arg1 = "squash";
- } else if (template_file && !stat(template_file, &statbuf)) {
+ } else if (template_file) {
if (strbuf_read_file(&sb, template_file, 0) < 0)
die_errno("could not read '%s'", template_file);
hook_arg1 = "template";
else if (in_merge)
hook_arg1 = "merge";
+ if (squash_message) {
+ /*
+ * If squash_commit was used for the commit subject,
+ * then we're possibly hijacking other commit log options.
+ * Reset the hook args to tell the real story.
+ */
+ hook_arg1 = "message";
+ hook_arg2 = "";
+ }
+
fp = fopen(git_path(commit_editmsg), "w");
if (fp == NULL)
die_errno("could not open '%s'", git_path(commit_editmsg));
strbuf_release(&sb);
- determine_author_info();
+ /* This checks and barfs if author is badly specified */
+ determine_author_info(author_ident);
/* This checks if committer ident is explicitly given */
- git_committer_info(0);
+ strbuf_addstr(&committer_ident, git_committer_info(0));
if (use_editor && include_status) {
- char *author_ident;
- const char *committer_ident;
-
+ char *ai_tmp, *ci_tmp;
if (in_merge)
fprintf(fp,
"#\n"
if (only_include_assumed)
fprintf(fp, "# %s\n", only_include_assumed);
- author_ident = xstrdup(fmt_name(author_name, author_email));
- committer_ident = fmt_name(getenv("GIT_COMMITTER_NAME"),
- getenv("GIT_COMMITTER_EMAIL"));
- if (strcmp(author_ident, committer_ident))
+ ai_tmp = cut_ident_timestamp_part(author_ident->buf);
+ ci_tmp = cut_ident_timestamp_part(committer_ident.buf);
+ if (strcmp(author_ident->buf, committer_ident.buf))
fprintf(fp,
"%s"
"# Author: %s\n",
ident_shown++ ? "" : "#\n",
- author_ident);
- free(author_ident);
+ author_ident->buf);
if (!user_ident_sufficiently_given())
fprintf(fp,
"%s"
"# Committer: %s\n",
ident_shown++ ? "" : "#\n",
- committer_ident);
+ committer_ident.buf);
if (ident_shown)
fprintf(fp, "#\n");
s->use_color = 0;
commitable = run_status(fp, index_file, prefix, 1, s);
s->use_color = saved_color_setting;
+
+ *ai_tmp = ' ';
+ *ci_tmp = ' ';
} else {
unsigned char sha1[20];
const char *parent = "HEAD";
else
commitable = index_differs_from(parent, 0);
}
+ strbuf_release(&committer_ident);
fclose(fp);
if (force_author && renew_authorship)
die("Using both --reset-author and --author does not make sense");
- if (logfile || message.len || use_message)
+ if (logfile || message.len || use_message || fixup_message)
use_editor = 0;
if (edit_flag)
use_editor = 1;
die("You have nothing to amend.");
if (amend && in_merge)
die("You are in the middle of a merge -- cannot amend.");
-
+ if (fixup_message && squash_message)
+ die("Options --squash and --fixup cannot be used together");
if (use_message)
f++;
if (edit_message)
f++;
+ if (fixup_message)
+ f++;
if (logfile)
f++;
if (f > 1)
- die("Only one of -c/-C/-F can be used.");
+ die("Only one of -c/-C/-F/--fixup can be used.");
if (message.len && f > 0)
- die("Option -m cannot be combined with -c/-C/-F.");
+ die("Option -m cannot be combined with -c/-C/-F/--fixup.");
if (edit_message)
use_message = edit_message;
- if (amend && !use_message)
+ if (amend && !use_message && !fixup_message)
use_message = "HEAD";
if (!use_message && renew_authorship)
die("--reset-author can be used only with -C, -c or --amend.");
if (use_message) {
- unsigned char sha1[20];
- static char utf8[] = "UTF-8";
const char *out_enc;
- char *enc, *end;
struct commit *commit;
- if (get_sha1(use_message, sha1))
+ commit = lookup_commit_reference_by_name(use_message);
+ if (!commit)
die("could not lookup commit %s", use_message);
- commit = lookup_commit_reference(sha1);
- if (!commit || parse_commit(commit))
- die("could not parse commit %s", use_message);
-
- enc = strstr(commit->buffer, "\nencoding");
- if (enc) {
- end = strchr(enc + 10, '\n');
- enc = xstrndup(enc + 10, end - (enc + 10));
- } else {
- enc = utf8;
- }
- out_enc = git_commit_encoding ? git_commit_encoding : utf8;
-
- if (strcmp(out_enc, enc))
- use_message_buffer =
- reencode_string(commit->buffer, out_enc, enc);
+ out_enc = get_commit_output_encoding();
+ use_message_buffer = logmsg_reencode(commit, out_enc);
/*
* If we failed to reencode the buffer, just copy it
*/
if (use_message_buffer == NULL)
use_message_buffer = xstrdup(commit->buffer);
- if (enc != utf8)
- free(enc);
}
if (!!also + !!only + !!all + !!interactive > 1)
{
if (!strcasecmp(var+offset, "header"))
return WT_STATUS_HEADER;
+ if (!strcasecmp(var+offset, "branch"))
+ return WT_STATUS_ONBRANCH;
if (!strcasecmp(var+offset, "updated")
|| !strcasecmp(var+offset, "added"))
return WT_STATUS_UPDATED;
int fd;
unsigned char sha1[20];
static struct option builtin_status_options[] = {
- OPT__VERBOSE(&verbose),
+ OPT__VERBOSE(&verbose, "be verbose"),
OPT_SET_INT('s', "short", &status_format,
"show status concisely", STATUS_FORMAT_SHORT),
OPT_BOOLEAN('b', "branch", &status_show_branch,
"show branch information"),
OPT_SET_INT(0, "porcelain", &status_format,
- "show porcelain output format",
+ "machine-readable output",
STATUS_FORMAT_PORCELAIN),
OPT_BOOLEAN('z', "null", &null_termination,
"terminate entries with NUL"),
OPT_END(),
};
+ if (argc == 2 && !strcmp(argv[1], "-h"))
+ usage_with_options(builtin_status_usage, builtin_status_options);
+
if (null_termination && status_format == STATUS_FORMAT_LONG)
status_format = STATUS_FORMAT_PORCELAIN;
refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, s.pathspec, NULL, NULL);
fd = hold_locked_index(&index_lock, 0);
- if (0 <= fd) {
- if (active_cache_changed &&
- !write_cache(fd, active_cache, active_nr))
- commit_locked_index(&index_lock);
- else
- rollback_lock_file(&index_lock);
- }
+ if (0 <= fd)
+ update_index_if_able(&the_index, &index_lock);
s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
s.in_merge = in_merge;
int cmd_commit(int argc, const char **argv, const char *prefix)
{
struct strbuf sb = STRBUF_INIT;
+ struct strbuf author_ident = STRBUF_INIT;
const char *index_file, *reflog_msg;
char *nl, *p;
unsigned char commit_sha1[20];
int allow_fast_forward = 1;
struct wt_status s;
+ if (argc == 2 && !strcmp(argv[1], "-h"))
+ usage_with_options(builtin_commit_usage, builtin_commit_options);
+
wt_status_prepare(&s);
git_config(git_commit_config, &s);
in_merge = file_exists(git_path("MERGE_HEAD"));
/* Set up everything for writing the commit object. This includes
running hooks, writing the trees, and interacting with the user. */
- if (!prepare_to_commit(index_file, prefix, &s)) {
+ if (!prepare_to_commit(index_file, prefix, &s, &author_ident)) {
rollback_index_files();
return 1;
}
}
if (commit_tree(sb.buf, active_cache_tree->sha1, parents, commit_sha1,
- fmt_ident(author_name, author_email, author_date,
- IDENT_ERROR_ON_NO_NAME))) {
+ author_ident.buf)) {
rollback_index_files();
die("failed to write commit object");
}
+ strbuf_release(&author_ident);
ref_lock = lock_any_ref_for_update("HEAD",
initial_commit ? NULL : head_sha1,
diff --combined builtin/diff.c
index 42822cd5374dbcf0e63c17078a55284c432ddc77,bab4bd9f57af2ad663c962fde33fa6934f7518b2..d4d80c982e99f9a16e4e5228a963d1f2f1836bfb
--- 1/builtin/diff.c
--- 2/builtin/diff.c
+++ b/builtin/diff.c
};
static const char builtin_diff_usage[] =
-"git diff <options> <rev>{0,2} -- <path>*";
+"git diff [<options>] [<commit> [<commit>]] [--] [<path>...]";
static void stuff_change(struct diff_options *opt,
unsigned old_mode, unsigned new_mode,
discard_cache();
read_cache();
refresh_cache(REFRESH_QUIET|REFRESH_UNMERGED);
-
- if (active_cache_changed &&
- !write_cache(fd, active_cache, active_nr))
- commit_locked_index(lock_file);
-
- rollback_lock_file(lock_file);
+ update_index_if_able(&the_index, lock_file);
}
static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv)
else if (!strcmp(arg, "--cached") ||
!strcmp(arg, "--staged")) {
add_head_to_pending(&rev);
- if (!rev.pending.nr)
- die("No HEAD commit to compare with (yet)");
+ if (!rev.pending.nr) {
+ struct tree *tree;
+ tree = lookup_tree((const unsigned char*)EMPTY_TREE_SHA1_BIN);
+ add_pending_object(&rev, &tree->object, "HEAD");
+ }
break;
}
}
diff --combined cache.h
index 50de992c5c1d51fe6ad50c40c152bd63f84869d0,9a3cc8ef1a0473287f238f66da3005be96a27ab1..342b4100f12d5a56262a13290c27298431e82325
+++ b/cache.h
*
* In-memory only flags
*/
-#define CE_UPDATE (0x10000)
-#define CE_REMOVE (0x20000)
-#define CE_UPTODATE (0x40000)
-#define CE_ADDED (0x80000)
+#define CE_UPDATE (1 << 16)
+#define CE_REMOVE (1 << 17)
+#define CE_UPTODATE (1 << 18)
+#define CE_ADDED (1 << 19)
-#define CE_HASHED (0x100000)
-#define CE_UNHASHED (0x200000)
-#define CE_CONFLICTED (0x800000)
+#define CE_HASHED (1 << 20)
+#define CE_UNHASHED (1 << 21)
+#define CE_WT_REMOVE (1 << 22) /* remove in work directory */
+#define CE_CONFLICTED (1 << 23)
-#define CE_WT_REMOVE (0x400000) /* remove in work directory */
-
-#define CE_UNPACKED (0x1000000)
+#define CE_UNPACKED (1 << 24)
+#define CE_NEW_SKIP_WORKTREE (1 << 25)
/*
* Extended on-disk flags
*/
-#define CE_INTENT_TO_ADD 0x20000000
-#define CE_SKIP_WORKTREE 0x40000000
+#define CE_INTENT_TO_ADD (1 << 29)
+#define CE_SKIP_WORKTREE (1 << 30)
/* CE_EXTENDED2 is for future extension */
-#define CE_EXTENDED2 0x80000000
+#define CE_EXTENDED2 (1 << 31)
#define CE_EXTENDED_FLAGS (CE_INTENT_TO_ADD | CE_SKIP_WORKTREE)
else
return DT_UNKNOWN;
}
-#define canon_mode(mode) \
- (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \
- S_ISLNK(mode) ? S_IFLNK : S_ISDIR(mode) ? S_IFDIR : S_IFGITLINK)
+static inline unsigned int canon_mode(unsigned int mode)
+{
+ if (S_ISREG(mode))
+ return S_IFREG | ce_permissions(mode);
+ if (S_ISLNK(mode))
+ return S_IFLNK;
+ if (S_ISDIR(mode))
+ return S_IFDIR;
+ return S_IFGITLINK;
+}
#define flexible_size(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
#define cache_entry_size(len) flexible_size(cache_entry,len)
extern void setup_work_tree(void);
extern const char *setup_git_directory_gently(int *);
extern const char *setup_git_directory(void);
-extern const char *prefix_path(const char *prefix, int len, const char *path);
+extern char *prefix_path(const char *prefix, int len, const char *path);
extern const char *prefix_filename(const char *prefix, int len, const char *path);
extern int check_filename(const char *prefix, const char *name);
extern void verify_filename(const char *prefix, const char *name);
* at least 'nr' entries; the number of entries currently allocated
* is 'alloc', using the standard growing factor alloc_nr() macro.
*
- * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
+ * DO NOT USE any expression with side-effect for 'x', 'nr', or 'alloc'.
*/
#define ALLOC_GROW(x, nr, alloc) \
do { \
extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
extern int commit_lock_file(struct lock_file *);
+ extern void update_index_if_able(struct index_state *, struct lock_file *);
extern int hold_locked_index(struct lock_file *, int);
extern int commit_locked_index(struct lock_file *);
extern int trust_ctime;
extern int quote_path_fully;
extern int has_symlinks;
+extern int minimum_abbrev, default_abbrev;
extern int ignore_case;
extern int assume_unchanged;
extern int prefer_symlink_refs;
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;
enum push_default_type {
PUSH_DEFAULT_NOTHING = 0,
PUSH_DEFAULT_MATCHING,
- PUSH_DEFAULT_TRACKING,
+ PUSH_DEFAULT_UPSTREAM,
PUSH_DEFAULT_CURRENT
};
#define EMPTY_TREE_SHA1_HEX \
"4b825dc642cb6eb9a060e54bf8d69288fbee4904"
-#define EMPTY_TREE_SHA1_BIN \
+#define EMPTY_TREE_SHA1_BIN_LITERAL \
"\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60" \
"\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04"
+#define EMPTY_TREE_SHA1_BIN \
+ ((const unsigned char *) EMPTY_TREE_SHA1_BIN_LITERAL)
int git_mkstemp(char *path, size_t n, const char *template);
}
/* Convert to/from hex/sha1 representation */
-#define MINIMUM_ABBREV 4
-#define DEFAULT_ABBREV 7
+#define MINIMUM_ABBREV minimum_abbrev
+#define DEFAULT_ABBREV default_abbrev
struct object_context {
unsigned char tree[20];
extern int has_symlink_leading_path(const char *name, int len);
extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
-extern int has_symlink_or_noent_leading_path(const char *name, int len);
+extern int check_leading_path(const char *name, int len);
extern int has_dirs_only_path(const char *name, int len, int prefix_len);
extern void schedule_dir_for_removal(const char *name, int len);
extern void remove_scheduled_dirs(void);
time_t mtime;
int pack_fd;
unsigned pack_local:1,
- pack_keep:1;
+ pack_keep:1,
+ do_not_close:1;
unsigned char sha1[20];
/* something like ".git/objects/pack/xxxxx.pack" */
char pack_name[FLEX_ARRAY]; /* more */
extern int git_config_parse_environment(void);
extern int git_config_from_parameters(config_fn_t fn, void *data);
extern int git_config(config_fn_t fn, void *);
+extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
extern int git_parse_ulong(const char *, unsigned long *);
extern int git_config_int(const char *, const char *);
extern unsigned long git_config_ulong(const char *, const char *);
extern int git_config_string(const char **, const char *, const char *);
extern int git_config_pathname(const char **, const char *, const char *);
extern int git_config_set(const char *, const char *);
+extern int git_config_parse_key(const char *, char **, int *);
extern int git_config_set_multivar(const char *, const char *, const char *, int);
extern int git_config_rename_section(const char *, const char *);
extern const char *git_etc_gitconfig(void);
extern int git_config_system(void);
extern int git_config_global(void);
extern int config_error_nonbool(const char *);
+extern const char *get_log_output_encoding(void);
+extern const char *get_commit_output_encoding(void);
+
extern const char *config_exclusive_filename;
#define MAX_GITNAME (1000)
extern void trace_printf(const char *format, ...);
__attribute__((format (printf, 2, 3)))
extern void trace_argv_printf(const char **argv, const char *format, ...);
+extern void trace_repo_setup(const char *prefix);
/* convert.c */
/* returns 1 if *dst was used */
/*
* whitespace rules.
* used by both diff and apply
+ * last two digits are tab width
*/
-#define WS_BLANK_AT_EOL 01
-#define WS_SPACE_BEFORE_TAB 02
-#define WS_INDENT_WITH_NON_TAB 04
-#define WS_CR_AT_EOL 010
-#define WS_BLANK_AT_EOF 020
-#define WS_TAB_IN_INDENT 040
+#define WS_BLANK_AT_EOL 0100
+#define WS_SPACE_BEFORE_TAB 0200
+#define WS_INDENT_WITH_NON_TAB 0400
+#define WS_CR_AT_EOL 01000
+#define WS_BLANK_AT_EOF 02000
+#define WS_TAB_IN_INDENT 04000
#define WS_TRAILING_SPACE (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
-#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB)
+#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB|8)
+#define WS_TAB_WIDTH_MASK 077
extern unsigned whitespace_rule_cfg;
extern unsigned whitespace_rule(const char *);
extern unsigned parse_whitespace_rule(const char *);
extern char *whitespace_error_string(unsigned ws);
extern void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
+#define ws_tab_width(rule) ((rule) & WS_TAB_WIDTH_MASK)
/* ls-files */
int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset);
/* git.c */
struct startup_info {
int have_repository;
+ const char *prefix;
};
extern struct startup_info *startup_info;
diff --combined read-cache.c
index 4f2e890b01b0c27ef2e49080e1fd34bf67e969c7,971e27705c37b7a1a5708026043dd48a15e7e87f..0480d9455cec042cf128e4d92bbc44a9dcc3fe32
--- 1/read-cache.c
--- 2/read-cache.c
+++ b/read-cache.c
ce->ce_mode = ce_mode_from_stat(ent, st_mode);
}
+ /* When core.ignorecase=true, determine if a directory of the same name but differing
+ * case already exists within the Git repository. If it does, ensure the directory
+ * case of the file being added to the repository matches (is folded into) the existing
+ * entry's directory case.
+ */
+ if (ignore_case) {
+ const char *startPtr = ce->name;
+ const char *ptr = startPtr;
+ while (*ptr) {
+ while (*ptr && *ptr != '/')
+ ++ptr;
+ if (*ptr == '/') {
+ struct cache_entry *foundce;
+ ++ptr;
+ foundce = index_name_exists(&the_index, ce->name, ptr - ce->name, ignore_case);
+ if (foundce) {
+ memcpy((void *)startPtr, foundce->name + (startPtr - ce->name), ptr - startPtr);
+ startPtr = ptr;
+ }
+ }
+ }
+ }
+
alias = index_name_exists(istate, ce->name, ce_namelen(ce), ignore_case);
if (alias && !ce_stage(alias) && !ie_match_stat(istate, alias, st, ce_option)) {
/* Nothing changed, really */
return result;
}
+ static int has_racy_timestamp(struct index_state *istate)
+ {
+ int entries = istate->cache_nr;
+ int i;
+
+ for (i = 0; i < entries; i++) {
+ struct cache_entry *ce = istate->cache[i];
+ if (is_racy_timestamp(istate, ce))
+ return 1;
+ }
+ return 0;
+ }
+
+ /*
+ * Opportunisticly update the index but do not complain if we can't
+ */
+ void update_index_if_able(struct index_state *istate, struct lock_file *lockfile)
+ {
+ if ((istate->cache_changed || has_racy_timestamp(istate)) &&
+ !write_index(istate, lockfile->fd))
+ commit_locked_index(lockfile);
+ else
+ rollback_lock_file(lockfile);
+ }
+
int write_index(struct index_state *istate, int newfd)
{
git_SHA_CTX c;