aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes/2.36.0.txt13
-rw-r--r--Documentation/config/repack.txt5
-rw-r--r--Documentation/git-maintenance.txt38
-rw-r--r--Documentation/gitattributes.txt2
-rw-r--r--attr.c1
-rw-r--r--attr.h1
-rw-r--r--block-sha1/sha1.c17
-rw-r--r--builtin/cat-file.c29
-rw-r--r--builtin/gc.c1
-rw-r--r--builtin/name-rev.c71
-rw-r--r--builtin/repack.c12
-rw-r--r--builtin/sparse-checkout.c1
-rw-r--r--builtin/stash.c1
-rw-r--r--builtin/submodule--helper.c248
-rw-r--r--contrib/completion/git-completion.bash4
-rw-r--r--diff.c11
-rwxr-xr-xgit-submodule.sh54
-rw-r--r--reflog.c2
-rw-r--r--sequencer.c10
-rw-r--r--t/helper/test-run-command.c1
-rwxr-xr-xt/perf/p1006-cat-file.sh12
-rwxr-xr-xt/t0410-partial-clone.sh19
-rwxr-xr-xt/t1410-reflog.sh9
-rwxr-xr-xt/t4015-diff-whitespace.sh12
-rw-r--r--t/t4018/kotlin-class5
-rw-r--r--t/t4018/kotlin-enum-class5
-rw-r--r--t/t4018/kotlin-fun5
-rw-r--r--t/t4018/kotlin-inheritace-class5
-rw-r--r--t/t4018/kotlin-inline-class5
-rw-r--r--t/t4018/kotlin-interface5
-rw-r--r--t/t4018/kotlin-nested-fun9
-rw-r--r--t/t4018/kotlin-public-class5
-rw-r--r--t/t4018/kotlin-sealed-class5
-rwxr-xr-xt/t4034-diff-words.sh1
-rw-r--r--t/t4034/kotlin/expect43
-rw-r--r--t/t4034/kotlin/post30
-rw-r--r--t/t4034/kotlin/pre30
-rwxr-xr-xt/t6120-describe.sh118
-rwxr-xr-xt/t6423-merge-rename-directories.sh10
-rwxr-xr-xt/t7406-submodule-update.sh26
-rwxr-xr-xt/t7408-submodule-reference.sh14
-rwxr-xr-xt/t7700-repack.sh50
-rw-r--r--userdiff.c12
43 files changed, 718 insertions, 239 deletions
diff --git a/Documentation/RelNotes/2.36.0.txt b/Documentation/RelNotes/2.36.0.txt
index f1449eb926..de91b846d1 100644
--- a/Documentation/RelNotes/2.36.0.txt
+++ b/Documentation/RelNotes/2.36.0.txt
@@ -78,6 +78,12 @@ UI, Workflows & Features
filtered by similar criteria you would give when making a
partial/lazy clone.
+ * A new built-in userdiff driver for kotlin has been added.
+
+ * "git repack" learned a new configuration to disable triggering of
+ age-old "update-server-info" command, which is rarely useful these
+ days.
+
Performance, Internal Implementation, Development Support etc.
@@ -142,6 +148,10 @@ Performance, Internal Implementation, Development Support etc.
* Remove unneeded <meta http-equiv=content-type...> from gitweb
output.
+ * "git name-rev" learned to use the generation numbers when setting
+ the lower bound of searching commits used to explain the revision,
+ when available, instead of committer time.
+
Fixes since v2.35
-----------------
@@ -360,3 +370,6 @@ Fixes since v2.35
(merge 6ee36364eb ab/diff-free-more later to maint).
(merge 63a36017fe nj/read-tree-doc-reffix later to maint).
(merge eed36fce38 sm/no-git-in-upstream-of-pipe-in-tests later to maint).
+ (merge c614beb933 ep/t6423-modernize later to maint).
+ (merge 57be9c6dee ab/reflog-prep-fix later to maint).
+ (merge 5327d8982a js/in-place-reverse-in-sequencer later to maint).
diff --git a/Documentation/config/repack.txt b/Documentation/config/repack.txt
index 9c413e177e..41ac6953c8 100644
--- a/Documentation/config/repack.txt
+++ b/Documentation/config/repack.txt
@@ -25,3 +25,8 @@ repack.writeBitmaps::
space and extra time spent on the initial repack. This has
no effect if multiple packfiles are created.
Defaults to true on bare repos, false otherwise.
+
+repack.updateServerInfo::
+ If set to false, linkgit:git-repack[1] will not run
+ linkgit:git-update-server-info[1]. Defaults to true. Can be overridden
+ when true by the `-n` option of linkgit:git-repack[1].
diff --git a/Documentation/git-maintenance.txt b/Documentation/git-maintenance.txt
index e2cfb68ab5..e56bad28c6 100644
--- a/Documentation/git-maintenance.txt
+++ b/Documentation/git-maintenance.txt
@@ -10,6 +10,8 @@ SYNOPSIS
--------
[verse]
'git maintenance' run [<options>]
+'git maintenance' start [--scheduler=<scheduler>]
+'git maintenance' (stop|register|unregister)
DESCRIPTION
@@ -29,6 +31,24 @@ Git repository.
SUBCOMMANDS
-----------
+run::
+ Run one or more maintenance tasks. If one or more `--task` options
+ are specified, then those tasks are run in that order. Otherwise,
+ the tasks are determined by which `maintenance.<task>.enabled`
+ config options are true. By default, only `maintenance.gc.enabled`
+ is true.
+
+start::
+ Start running maintenance on the current repository. This performs
+ the same config updates as the `register` subcommand, then updates
+ the background scheduler to run `git maintenance run --scheduled`
+ on an hourly basis.
+
+stop::
+ Halt the background maintenance schedule. The current repository
+ is not removed from the list of maintained repositories, in case
+ the background maintenance is restarted later.
+
register::
Initialize Git config values so any scheduled maintenance will
start running on this repository. This adds the repository to the
@@ -55,24 +75,6 @@ task:
setting `maintenance.auto = false` in the current repository. This config
setting will remain after a `git maintenance unregister` command.
-run::
- Run one or more maintenance tasks. If one or more `--task` options
- are specified, then those tasks are run in that order. Otherwise,
- the tasks are determined by which `maintenance.<task>.enabled`
- config options are true. By default, only `maintenance.gc.enabled`
- is true.
-
-start::
- Start running maintenance on the current repository. This performs
- the same config updates as the `register` subcommand, then updates
- the background scheduler to run `git maintenance run --scheduled`
- on an hourly basis.
-
-stop::
- Halt the background maintenance schedule. The current repository
- is not removed from the list of maintained repositories, in case
- the background maintenance is restarted later.
-
unregister::
Remove the current repository from background maintenance. This
only removes the repository from the configured list. It does not
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index a71dad2674..4b36d51beb 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -829,6 +829,8 @@ patterns are available:
- `java` suitable for source code in the Java language.
+- `kotlin` suitable for source code in the Kotlin language.
+
- `markdown` suitable for Markdown documents.
- `matlab` suitable for source code in the MATLAB and Octave languages.
diff --git a/attr.c b/attr.c
index 79adaa50ea..1626cade8b 100644
--- a/attr.c
+++ b/attr.c
@@ -14,7 +14,6 @@
#include "utf8.h"
#include "quote.h"
#include "thread-utils.h"
-#include "dir.h"
const char git_attr__true[] = "(builtin)true";
const char git_attr__false[] = "\0(builtin)false";
diff --git a/attr.h b/attr.h
index 3732505eda..3fb40cced0 100644
--- a/attr.h
+++ b/attr.h
@@ -121,7 +121,6 @@ struct git_attr;
/* opaque structures used internally for attribute collection */
struct all_attrs_item;
struct attr_stack;
-struct index_state;
/*
* Given a string, return the gitattribute object that
diff --git a/block-sha1/sha1.c b/block-sha1/sha1.c
index 1bb6e7c069..5974cd7dd3 100644
--- a/block-sha1/sha1.c
+++ b/block-sha1/sha1.c
@@ -11,27 +11,10 @@
#include "sha1.h"
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-
-/*
- * Force usage of rol or ror by selecting the one with the smaller constant.
- * It _can_ generate slightly smaller code (a constant of 1 is special), but
- * perhaps more importantly it's possibly faster on any uarch that does a
- * rotate with a loop.
- */
-
-#define SHA_ASM(op, x, n) ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; })
-#define SHA_ROL(x,n) SHA_ASM("rol", x, n)
-#define SHA_ROR(x,n) SHA_ASM("ror", x, n)
-
-#else
-
#define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r)))
#define SHA_ROL(X,n) SHA_ROT(X,n,32-(n))
#define SHA_ROR(X,n) SHA_ROT(X,32-(n),n)
-#endif
-
/*
* If you have 32 registers or more, the compiler can (and should)
* try to change the array[] accesses into registers. However, on
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 0663661c0b..50cf38999d 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -360,6 +360,13 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d
}
}
+static void print_default_format(struct strbuf *scratch, struct expand_data *data)
+{
+ strbuf_addf(scratch, "%s %s %"PRIuMAX"\n", oid_to_hex(&data->oid),
+ type_name(data->type),
+ (uintmax_t)data->size);
+}
+
/*
* If "pack" is non-NULL, then "offset" is the byte offset within the pack from
* which the object may be accessed (though note that we may also rely on
@@ -391,8 +398,14 @@ static void batch_object_write(const char *obj_name,
}
strbuf_reset(scratch);
- strbuf_expand(scratch, opt->format, expand_format, data);
- strbuf_addch(scratch, '\n');
+
+ if (!opt->format) {
+ print_default_format(scratch, data);
+ } else {
+ strbuf_expand(scratch, opt->format, expand_format, data);
+ strbuf_addch(scratch, '\n');
+ }
+
batch_write(opt, scratch->buf, scratch->len);
if (opt->batch_mode == BATCH_MODE_CONTENTS) {
@@ -646,6 +659,8 @@ static void batch_objects_command(struct batch_options *opt,
strbuf_release(&input);
}
+#define DEFAULT_FORMAT "%(objectname) %(objecttype) %(objectsize)"
+
static int batch_objects(struct batch_options *opt)
{
struct strbuf input = STRBUF_INIT;
@@ -654,9 +669,6 @@ static int batch_objects(struct batch_options *opt)
int save_warning;
int retval = 0;
- if (!opt->format)
- opt->format = "%(objectname) %(objecttype) %(objectsize)";
-
/*
* Expand once with our special mark_query flag, which will prime the
* object_info to be handed to oid_object_info_extended for each
@@ -664,12 +676,17 @@ static int batch_objects(struct batch_options *opt)
*/
memset(&data, 0, sizeof(data));
data.mark_query = 1;
- strbuf_expand(&output, opt->format, expand_format, &data);
+ strbuf_expand(&output,
+ opt->format ? opt->format : DEFAULT_FORMAT,
+ expand_format,
+ &data);
data.mark_query = 0;
strbuf_release(&output);
if (opt->transform_mode)
data.split_on_whitespace = 1;
+ if (opt->format && !strcmp(opt->format, DEFAULT_FORMAT))
+ opt->format = NULL;
/*
* If we are printing out the object, then always fill in the type,
* since we will want to decide whether or not to stream.
diff --git a/builtin/gc.c b/builtin/gc.c
index ffaf0daf5d..b335cffa33 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -30,7 +30,6 @@
#include "promisor-remote.h"
#include "refs.h"
#include "remote.h"
-#include "object-store.h"
#include "exec-cmd.h"
#include "hook.h"
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 929591269d..c59b5699fe 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -9,6 +9,7 @@
#include "prio-queue.h"
#include "hash-lookup.h"
#include "commit-slab.h"
+#include "commit-graph.h"
/*
* One day. See the 'name a rev shortly after epoch' test in t6120 when
@@ -26,9 +27,58 @@ struct rev_name {
define_commit_slab(commit_rev_name, struct rev_name);
+static timestamp_t generation_cutoff = GENERATION_NUMBER_INFINITY;
static timestamp_t cutoff = TIME_MAX;
static struct commit_rev_name rev_names;
+/* Disable the cutoff checks entirely */
+static void disable_cutoff(void)
+{
+ generation_cutoff = 0;
+ cutoff = 0;
+}
+
+/* Cutoff searching any commits older than this one */
+static void set_commit_cutoff(struct commit *commit)
+{
+
+ if (cutoff > commit->date)
+ cutoff = commit->date;
+
+ if (generation_cutoff) {
+ timestamp_t generation = commit_graph_generation(commit);
+
+ if (generation_cutoff > generation)
+ generation_cutoff = generation;
+ }
+}
+
+/* adjust the commit date cutoff with a slop to allow for slightly incorrect
+ * commit timestamps in case of clock skew.
+ */
+static void adjust_cutoff_timestamp_for_slop(void)
+{
+ if (cutoff) {
+ /* check for undeflow */
+ if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP)
+ cutoff = cutoff - CUTOFF_DATE_SLOP;
+ else
+ cutoff = TIME_MIN;
+ }
+}
+
+/* Check if a commit is before the cutoff. Prioritize generation numbers
+ * first, but use the commit timestamp if we lack generation data.
+ */
+static int commit_is_before_cutoff(struct commit *commit)
+{
+ if (generation_cutoff < GENERATION_NUMBER_INFINITY)
+ return generation_cutoff &&
+ commit_graph_generation(commit) < generation_cutoff;
+
+ return commit->date < cutoff;
+}
+
/* How many generations are maximally preferred over _one_ merge traversal? */
#define MERGE_TRAVERSAL_WEIGHT 65535
@@ -151,7 +201,7 @@ static void name_rev(struct commit *start_commit,
struct rev_name *start_name;
parse_commit(start_commit);
- if (start_commit->date < cutoff)
+ if (commit_is_before_cutoff(start_commit))
return;
start_name = create_or_update_name(start_commit, taggerdate, 0, 0,
@@ -181,7 +231,7 @@ static void name_rev(struct commit *start_commit,
int generation, distance;
parse_commit(parent);
- if (parent->date < cutoff)
+ if (commit_is_before_cutoff(parent))
continue;
if (parent_number > 1) {
@@ -568,7 +618,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
usage_with_options(name_rev_usage, opts);
}
if (all || annotate_stdin)
- cutoff = 0;
+ disable_cutoff();
for (; argc; argc--, argv++) {
struct object_id oid;
@@ -596,10 +646,8 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
continue;
}
- if (commit) {
- if (cutoff > commit->date)
- cutoff = commit->date;
- }
+ if (commit)
+ set_commit_cutoff(commit);
if (peel_tag) {
if (!commit) {
@@ -612,13 +660,8 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
add_object_array(object, *argv, &revs);
}
- if (cutoff) {
- /* check for undeflow */
- if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP)
- cutoff = cutoff - CUTOFF_DATE_SLOP;
- else
- cutoff = TIME_MIN;
- }
+ adjust_cutoff_timestamp_for_slop();
+
for_each_ref(name_ref, &data);
name_tips();
diff --git a/builtin/repack.c b/builtin/repack.c
index da1e364a75..d1a563d5b6 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -22,6 +22,7 @@ static int delta_base_offset = 1;
static int pack_kept_objects = -1;
static int write_bitmaps = -1;
static int use_delta_islands;
+static int run_update_server_info = 1;
static char *packdir, *packtmp_name, *packtmp;
static const char *const git_repack_usage[] = {
@@ -54,6 +55,10 @@ static int repack_config(const char *var, const char *value, void *cb)
use_delta_islands = git_config_bool(var, value);
return 0;
}
+ if (strcmp(var, "repack.updateserverinfo") == 0) {
+ run_update_server_info = git_config_bool(var, value);
+ return 0;
+ }
return git_default_config(var, value, cb);
}
@@ -620,7 +625,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
const char *unpack_unreachable = NULL;
int keep_unreachable = 0;
struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
- int no_update_server_info = 0;
struct pack_objects_args po_args = {NULL};
int geometric_factor = 0;
int write_midx = 0;
@@ -637,8 +641,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
N_("pass --no-reuse-delta to git-pack-objects")),
OPT_BOOL('F', NULL, &po_args.no_reuse_object,
N_("pass --no-reuse-object to git-pack-objects")),
- OPT_BOOL('n', NULL, &no_update_server_info,
- N_("do not run git-update-server-info")),
+ OPT_NEGBIT('n', NULL, &run_update_server_info,
+ N_("do not run git-update-server-info"), 1),
OPT__QUIET(&po_args.quiet, N_("be quiet")),
OPT_BOOL('l', "local", &po_args.local,
N_("pass --local to git-pack-objects")),
@@ -939,7 +943,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
prune_shallow(PRUNE_QUICK);
}
- if (!no_update_server_info)
+ if (run_update_server_info)
update_server_info(0);
remove_temporary_files();
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 7f02e4352a..0217d44c5b 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -8,7 +8,6 @@
#include "run-command.h"
#include "strbuf.h"
#include "string-list.h"
-#include "cache.h"
#include "cache-tree.h"
#include "lockfile.h"
#include "resolve-undo.h"
diff --git a/builtin/stash.c b/builtin/stash.c
index 242e73cbb0..ccdfdab44b 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -16,7 +16,6 @@
#include "log-tree.h"
#include "diffcore.h"
#include "exec-cmd.h"
-#include "entry.h"
#include "reflog.h"
#define INCLUDE_ALL_FILES 2
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 2f7c58362b..5301612d24 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -31,11 +31,13 @@
typedef void (*each_submodule_fn)(const struct cache_entry *list_item,
void *cb_data);
-static char *get_default_remote(void)
+static char *repo_get_default_remote(struct repository *repo)
{
char *dest = NULL, *ret;
struct strbuf sb = STRBUF_INIT;
- const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
+ struct ref_store *store = get_main_ref_store(repo);
+ const char *refname = refs_resolve_ref_unsafe(store, "HEAD", 0, NULL,
+ NULL);
if (!refname)
die(_("No such ref: %s"), "HEAD");
@@ -48,7 +50,7 @@ static char *get_default_remote(void)
die(_("Expecting a full ref name, got %s"), refname);
strbuf_addf(&sb, "branch.%s.remote", refname);
- if (git_config_get_string(sb.buf, &dest))
+ if (repo_config_get_string(repo, sb.buf, &dest))
ret = xstrdup("origin");
else
ret = dest;
@@ -57,19 +59,17 @@ static char *get_default_remote(void)
return ret;
}
-static int print_default_remote(int argc, const char **argv, const char *prefix)
+static char *get_default_remote_submodule(const char *module_path)
{
- char *remote;
-
- if (argc != 1)
- die(_("submodule--helper print-default-remote takes no arguments"));
+ struct repository subrepo;
- remote = get_default_remote();
- if (remote)
- printf("%s\n", remote);
+ repo_submodule_init(&subrepo, the_repository, module_path, null_oid());
+ return repo_get_default_remote(&subrepo);
+}
- free(remote);
- return 0;
+static char *get_default_remote(void)
+{
+ return repo_get_default_remote(the_repository);
}
static int starts_with_dot_slash(const char *str)
@@ -247,11 +247,10 @@ static int resolve_relative_url_test(int argc, const char **argv, const char *pr
return 0;
}
-/* the result should be freed by the caller. */
-static char *get_submodule_displaypath(const char *path, const char *prefix)
+static char *do_get_submodule_displaypath(const char *path,
+ const char *prefix,
+ const char *super_prefix)
{
- const char *super_prefix = get_super_prefix();
-
if (prefix && super_prefix) {
BUG("cannot have prefix '%s' and superprefix '%s'",
prefix, super_prefix);
@@ -267,6 +266,13 @@ static char *get_submodule_displaypath(const char *path, const char *prefix)
}
}
+/* the result should be freed by the caller. */
+static char *get_submodule_displaypath(const char *path, const char *prefix)
+{
+ const char *super_prefix = get_super_prefix();
+ return do_get_submodule_displaypath(path, prefix, super_prefix);
+}
+
static char *compute_rev_name(const char *sub_path, const char* object_id)
{
struct strbuf sb = STRBUF_INIT;
@@ -588,18 +594,22 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
struct init_cb {
const char *prefix;
+ const char *superprefix;
unsigned int flags;
};
#define INIT_CB_INIT { 0 }
static void init_submodule(const char *path, const char *prefix,
- unsigned int flags)
+ const char *superprefix, unsigned int flags)
{
const struct submodule *sub;
struct strbuf sb = STRBUF_INIT;
char *upd = NULL, *url = NULL, *displaypath;
- displaypath = get_submodule_displaypath(path, prefix);
+ /* try superprefix from the environment, if it is not passed explicitly */
+ if (!superprefix)
+ superprefix = get_super_prefix();
+ displaypath = do_get_submodule_displaypath(path, prefix, superprefix);
sub = submodule_from_path(the_repository, null_oid(), path);
@@ -673,7 +683,7 @@ static void init_submodule(const char *path, const char *prefix,
static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data)
{
struct init_cb *info = cb_data;
- init_submodule(list_item->name, info->prefix, info->flags);
+ init_submodule(list_item->name, info->prefix, info->superprefix, info->flags);
}
static int module_init(int argc, const char **argv, const char *prefix)
@@ -1343,9 +1353,8 @@ static void sync_submodule(const char *path, const char *prefix,
{
const struct submodule *sub;
char *remote_key = NULL;
- char *sub_origin_url, *super_config_url, *displaypath;
+ char *sub_origin_url, *super_config_url, *displaypath, *default_remote;
struct strbuf sb = STRBUF_INIT;
- struct child_process cp = CHILD_PROCESS_INIT;
char *sub_config_path = NULL;
if (!is_submodule_active(the_repository, path))
@@ -1384,21 +1393,15 @@ static void sync_submodule(const char *path, const char *prefix,
if (!is_submodule_populated_gently(path, NULL))
goto cleanup;
- prepare_submodule_repo_env(&cp.env_array);
- cp.git_cmd = 1;
- cp.dir = path;
- strvec_pushl(&cp.args, "submodule--helper",
- "print-default-remote", NULL);
-
strbuf_reset(&sb);
- if (capture_command(&cp, &sb, 0))
+ default_remote = get_default_remote_submodule(path);
+ if (!default_remote)
die(_("failed to get the default remote for submodule '%s'"),
path);
- strbuf_strip_suffix(&sb, "\n");
- remote_key = xstrfmt("remote.%s.url", sb.buf);
+ remote_key = xstrfmt("remote.%s.url", default_remote);
+ free(default_remote);
- strbuf_reset(&sb);
submodule_to_gitdir(&sb, path);
strbuf_addstr(&sb, "/config");
@@ -1957,29 +1960,6 @@ static void determine_submodule_update_strategy(struct repository *r,
free(key);
}
-static int module_update_module_mode(int argc, const char **argv, const char *prefix)
-{
- const char *path, *update = NULL;
- int just_cloned;
- struct submodule_update_strategy update_strategy = { .type = SM_UPDATE_CHECKOUT };
-
- if (argc < 3 || argc > 4)
- die("submodule--helper update-module-clone expects <just-cloned> <path> [<update>]");
-
- just_cloned = git_config_int("just_cloned", argv[1]);
- path = argv[2];
-
- if (argc == 4)
- update = argv[3];
-
- determine_submodule_update_strategy(the_repository,
- just_cloned, path, update,
- &update_strategy);
- fputs(submodule_strategy_to_string(&update_strategy), stdout);
-
- return 0;
-}
-
struct update_clone_data {
const struct submodule *sub;
struct object_id oid;
@@ -2020,6 +2000,7 @@ struct submodule_update_clone {
int failed_clones_nr, failed_clones_alloc;
int max_jobs;
+ unsigned int init;
};
#define SUBMODULE_UPDATE_CLONE_INIT { \
.list = MODULE_LIST_INIT, \
@@ -2038,10 +2019,11 @@ struct update_data {
struct object_id suboid;
struct submodule_update_strategy update_strategy;
int depth;
- unsigned int force: 1;
- unsigned int quiet: 1;
- unsigned int nofetch: 1;
- unsigned int just_cloned: 1;
+ unsigned int force;
+ unsigned int quiet;
+ unsigned int nofetch;
+ unsigned int just_cloned;
+ unsigned int remote;
};
#define UPDATE_DATA_INIT { .update_strategy = SUBMODULE_UPDATE_STRATEGY_INIT }
@@ -2475,6 +2457,16 @@ static int do_run_update_procedure(struct update_data *ud)
return run_update_command(ud, subforce);
}
+/*
+ * NEEDSWORK: As we convert "git submodule update" to C,
+ * update_submodule2() will invoke more and more functions, making it
+ * difficult to preserve the function ordering without forward
+ * declarations.
+ *
+ * When the conversion is complete, this forward declaration will be
+ * unnecessary and should be removed.
+ */
+static int update_submodule2(struct update_data *update_data);
static void update_submodule(struct update_clone_data *ucd)
{
fprintf(stdout, "dummy %s %d\t%s\n",
@@ -2518,6 +2510,8 @@ static int update_clone(int argc, const char **argv, const char *prefix)
int ret;
struct option module_update_clone_options[] = {
+ OPT_BOOL(0, "init", &suc.init,
+ N_("initialize uninitialized submodules before update")),
OPT_STRING(0, "prefix", &prefix,
N_("path"),
N_("path into the working tree")),
@@ -2551,7 +2545,12 @@ static int update_clone(int argc, const char **argv, const char *prefix)
};
const char *const git_submodule_helper_usage[] = {
- N_("git submodule--helper update-clone [--prefix=<path>] [<path>...]"),
+ N_("git submodule [--quiet] update"
+ " [--init [--filter=<filter-spec>]] [--remote]"
+ " [-N|--no-fetch] [-f|--force]"
+ " [--checkout|--merge|--rebase]"
+ " [--[no-]recommend-shallow] [--reference <repository>]"
+ " [--recursive] [--[no-]single-branch] [--] [<path>...]"),
NULL
};
suc.prefix = prefix;
@@ -2562,6 +2561,19 @@ static int update_clone(int argc, const char **argv, const char *prefix)
memset(&filter_options, 0, sizeof(filter_options));
argc = parse_options(argc, argv, prefix, module_update_clone_options,
git_submodule_helper_usage, 0);
+
+ if (filter_options.choice && !suc.init) {
+ /*
+ * NEEDSWORK: Don't use usage_with_options() because the
+ * usage string is for "git submodule update", but the
+ * options are for "git submodule--helper update-clone".
+ *
+ * This will no longer be an issue when "update-clone"
+ * is replaced by "git submodule--helper update".
+ */
+ usage(git_submodule_helper_usage[0]);
+ }
+
suc.filter_options = &filter_options;
if (update)
@@ -2576,6 +2588,29 @@ static int update_clone(int argc, const char **argv, const char *prefix)
if (pathspec.nr)
suc.warn_if_uninitialized = 1;
+ if (suc.init) {
+ struct module_list list = MODULE_LIST_INIT;
+ struct init_cb info = INIT_CB_INIT;
+
+ if (module_list_compute(argc, argv, suc.prefix,
+ &pathspec, &list) < 0)
+ return 1;
+
+ /*
+ * If there are no path args and submodule.active is set then,
+ * by default, only initialize 'active' modules.
+ */
+ if (!argc && git_config_get_value_multi("submodule.active"))
+ module_list_active(&list);
+
+ info.prefix = suc.prefix;
+ info.superprefix = suc.recursive_prefix;
+ if (suc.quiet)
+ info.flags |= OPT_QUIET;
+
+ for_each_listed_submodule(&list, init_submodule_cb, &info);
+ }
+
ret = update_submodules(&suc);
list_objects_filter_release(&filter_options);
return ret;
@@ -2583,16 +2618,17 @@ static int update_clone(int argc, const char **argv, const char *prefix)
static int run_update_procedure(int argc, const char **argv, const char *prefix)
{
- int force = 0, quiet = 0, nofetch = 0, just_cloned = 0;
char *prefixed_path, *update = NULL;
struct update_data update_data = UPDATE_DATA_INIT;
struct option options[] = {
- OPT__QUIET(&quiet, N_("suppress output for update by rebase or merge")),
- OPT__FORCE(&force, N_("force checkout updates"), 0),
- OPT_BOOL('N', "no-fetch", &nofetch,
+ OPT__QUIET(&update_data.quiet,
+ N_("suppress output for update by rebase or merge")),
+ OPT__FORCE(&update_data.force, N_("force checkout updates"),
+ 0),
+ OPT_BOOL('N', "no-fetch", &update_data.nofetch,
N_("don't fetch new objects from the remote site")),
- OPT_BOOL(0, "just-cloned", &just_cloned,
+ OPT_BOOL(0, "just-cloned", &update_data.just_cloned,
N_("overrides update mode in case the repository is a fresh clone")),
OPT_INTEGER(0, "depth", &update_data.depth, N_("depth for shallow fetch")),
OPT_STRING(0, "prefix", &prefix,
@@ -2607,9 +2643,8 @@ static int run_update_procedure(int argc, const char **argv, const char *prefix)
OPT_CALLBACK_F(0, "oid", &update_data.oid, N_("sha1"),
N_("SHA1 expected by superproject"), PARSE_OPT_NONEG,
parse_opt_object_id),
- OPT_CALLBACK_F(0, "suboid", &update_data.suboid, N_("subsha1"),
- N_("SHA1 of submodule's HEAD"), PARSE_OPT_NONEG,
- parse_opt_object_id),
+ OPT_BOOL(0, "remote", &update_data.remote,
+ N_("use SHA-1 of submodule's remote tracking branch")),
OPT_END()
};
@@ -2623,10 +2658,6 @@ static int run_update_procedure(int argc, const char **argv, const char *prefix)
if (argc != 1)
usage_with_options(usage, options);
- update_data.force = !!force;
- update_data.quiet = !!quiet;
- update_data.nofetch = !!nofetch;
- update_data.just_cloned = !!just_cloned;
update_data.sm_path = argv[0];
if (update_data.recursive_prefix)
@@ -2641,11 +2672,7 @@ static int run_update_procedure(int argc, const char **argv, const char *prefix)
&update_data.update_strategy);
free(prefixed_path);
-
- if (!oideq(&update_data.oid, &update_data.suboid) || update_data.force)
- return do_run_update_procedure(&update_data);
-
- return 3;
+ return update_submodule2(&update_data);
}
static int resolve_relative_path(int argc, const char **argv, const char *prefix)
@@ -2697,23 +2724,6 @@ static const char *remote_submodule_branch(const char *path)
return branch;
}
-static int resolve_remote_submodule_branch(int argc, const char **argv,
- const char *prefix)
-{
- const char *ret;
- struct strbuf sb = STRBUF_INIT;
- if (argc != 2)
- die("submodule--helper remote-branch takes exactly one arguments, got %d", argc);
-
- ret = remote_submodule_branch(argv[1]);
- if (!ret)
- die("submodule %s doesn't exist", argv[1]);
-
- printf("%s", ret);
- strbuf_release(&sb);
- return 0;
-}
-
static int push_check(int argc, const char **argv, const char *prefix)
{
struct remote *remote;
@@ -2791,17 +2801,11 @@ static int push_check(int argc, const char **argv, const char *prefix)
return 0;
}
-static int ensure_core_worktree(int argc, const char **argv, const char *prefix)
+static void ensure_core_worktree(const char *path)
{
- const char *path;
const char *cw;
struct repository subrepo;
- if (argc != 2)
- BUG("submodule--helper ensure-core-worktree <path>");
-
- path = argv[1];
-
if (repo_submodule_init(&subrepo, the_repository, path, null_oid()))
die(_("could not get a repository handle for submodule '%s'"), path);
@@ -2821,8 +2825,6 @@ static int ensure_core_worktree(int argc, const char **argv, const char *prefix)
free(abs_path);
strbuf_release(&sb);
}
-
- return 0;
}
static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
@@ -3045,6 +3047,42 @@ static int module_create_branch(int argc, const char **argv, const char *prefix)
force, reflog, quiet, track, dry_run);
return 0;
}
+
+/* NEEDSWORK: this is a temporary name until we delete update_submodule() */
+static int update_submodule2(struct update_data *update_data)
+{
+ ensure_core_worktree(update_data->sm_path);
+ if (update_data->just_cloned)
+ oidcpy(&update_data->suboid, null_oid());
+ else if (resolve_gitlink_ref(update_data->sm_path, "HEAD", &update_data->suboid))
+ die(_("Unable to find current revision in submodule path '%s'"),
+ update_data->displaypath);
+
+ if (update_data->remote) {
+ char *remote_name = get_default_remote_submodule(update_data->sm_path);
+ const char *branch = remote_submodule_branch(update_data->sm_path);
+ char *remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch);
+
+ if (!update_data->nofetch) {
+ if (fetch_in_submodule(update_data->sm_path, update_data->depth,
+ 0, NULL))
+ die(_("Unable to fetch in submodule path '%s'"),
+ update_data->sm_path);
+ }
+
+ if (resolve_gitlink_ref(update_data->sm_path, remote_ref, &update_data->oid))
+ die(_("Unable to find %s revision in submodule path '%s'"),
+ remote_ref, update_data->sm_path);
+
+ free(remote_ref);
+ }
+
+ if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force)
+ return do_run_update_procedure(update_data);
+
+ return 3;
+}
+
struct add_data {
const char *prefix;
const char *branch;
@@ -3433,20 +3471,16 @@ static struct cmd_struct commands[] = {
{"name", module_name, 0},
{"clone", module_clone, 0},
{"add", module_add, SUPPORT_SUPER_PREFIX},
- {"update-module-mode", module_update_module_mode, 0},
{"update-clone", update_clone, 0},
{"run-update-procedure", run_update_procedure, 0},
- {"ensure-core-worktree", ensure_core_worktree, 0},
{"relative-path", resolve_relative_path, 0},
{"resolve-relative-url-test", resolve_relative_url_test, 0},
{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
{"init", module_init, SUPPORT_SUPER_PREFIX},
{"status", module_status, SUPPORT_SUPER_PREFIX},
- {"print-default-remote", print_default_remote, 0},
{"sync", module_sync, SUPPORT_SUPER_PREFIX},
{"deinit", module_deinit, 0},
{"summary", module_summary, SUPPORT_SUPER_PREFIX},
- {"remote-branch", resolve_remote_submodule_branch, 0},
{"push-check", push_check, 0},
{"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
{"is-active", is_active, 0},
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 49a328aa8a..ba5c395d2d 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2890,6 +2890,10 @@ _git_restore ()
--*)
__gitcomp_builtin restore
;;
+ *)
+ if __git rev-parse --verify --quiet HEAD >/dev/null; then
+ __git_complete_index_file "--modified"
+ fi
esac
}
diff --git a/diff.c b/diff.c
index 6b22946cd0..ef7159968b 100644
--- a/diff.c
+++ b/diff.c
@@ -800,6 +800,14 @@ static void append_emitted_diff_symbol(struct diff_options *o,
f->line = e->line ? xmemdupz(e->line, e->len) : NULL;
}
+static void free_emitted_diff_symbols(struct emitted_diff_symbols *e)
+{
+ if (!e)
+ return;
+ free(e->buf);
+ free(e);
+}
+
struct moved_entry {
const struct emitted_diff_symbol *es;
struct moved_entry *next_line;
@@ -2150,7 +2158,6 @@ static void diff_words_flush(struct emit_callback *ecbdata)
for (i = 0; i < wol->nr; i++)
free((void *)wol->buf[i].line);
- free(wol->buf);
wol->nr = 0;
}
@@ -2228,7 +2235,7 @@ static void free_diff_words_data(struct emit_callback *ecbdata)
{
if (ecbdata->diff_words) {
diff_words_flush(ecbdata);
- free (ecbdata->diff_words->opt->emitted_symbols);
+ free_emitted_diff_symbols(ecbdata->diff_words->opt->emitted_symbols);
free (ecbdata->diff_words->opt);
free (ecbdata->diff_words->minus.text.ptr);
free (ecbdata->diff_words->minus.orig);
diff --git a/git-submodule.sh b/git-submodule.sh
index 87772ac891..aa8bdfca9d 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -247,20 +247,6 @@ cmd_deinit()
git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${force:+--force} ${deinit_all:+--all} -- "$@"
}
-# usage: fetch_in_submodule <module_path> [<depth>] [<sha1>]
-# Because arguments are positional, use an empty string to omit <depth>
-# but include <sha1>.
-fetch_in_submodule () (
- sanitize_submodule_env &&
- cd "$1" &&
- if test $# -eq 3
- then
- echo "$3" | git fetch ${GIT_QUIET:+--quiet} --stdin ${2:+"$2"}
- else
- git fetch ${GIT_QUIET:+--quiet} ${2:+"$2"}
- fi
-)
-
#
# Update each submodule path to correct revision, using clone and checkout as needed
#
@@ -370,19 +356,11 @@ cmd_update()
shift
done
- if test -n "$filter" && test "$init" != "1"
- then
- usage
- fi
-
- if test -n "$init"
- then
- cmd_init "--" "$@" || return
- fi
-
{
- git submodule--helper update-clone ${GIT_QUIET:+--quiet} \
+ git ${wt_prefix:+-C "$wt_prefix"} submodule--helper update-clone \
+ ${GIT_QUIET:+--quiet} \
${progress:+"--progress"} \
+ ${init:+--init} \
${wt_prefix:+--prefix "$wt_prefix"} \
${prefix:+--recursive-prefix "$prefix"} \
${update:+--update "$update"} \
@@ -402,33 +380,11 @@ cmd_update()
do
die_if_unmatched "$quickabort" "$sha1"
- git submodule--helper ensure-core-worktree "$sm_path" || exit 1
-
displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
- if test $just_cloned -eq 1
+ if test $just_cloned -eq 0
then
- subsha1=
- else
just_cloned=
- subsha1=$(sanitize_submodule_env; cd "$sm_path" &&
- git rev-parse --verify HEAD) ||
- die "fatal: $(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
- fi
-
- if test -n "$remote"
- then
- branch=$(git submodule--helper remote-branch "$sm_path")
- if test -z "$nofetch"
- then
- # Fetch remote before determining tracking $sha1
- fetch_in_submodule "$sm_path" $depth ||
- die "fatal: $(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
- fi
- remote_name=$(sanitize_submodule_env; cd "$sm_path" && git submodule--helper print-default-remote)
- sha1=$(sanitize_submodule_env; cd "$sm_path" &&
- git rev-parse --verify "${remote_name}/${branch}") ||
- die "fatal: $(eval_gettext "Unable to find current \${remote_name}/\${branch} revision in submodule path '\$sm_path'")"
fi
out=$(git submodule--helper run-update-procedure \
@@ -441,7 +397,7 @@ cmd_update()
${update:+--update "$update"} \
${prefix:+--recursive-prefix "$prefix"} \
${sha1:+--oid "$sha1"} \
- ${subsha1:+--suboid "$subsha1"} \
+ ${remote:+--remote} \
"--" \
"$sm_path")
diff --git a/reflog.c b/reflog.c
index 333fd8708f..47ba8620c5 100644
--- a/reflog.c
+++ b/reflog.c
@@ -334,6 +334,8 @@ void reflog_expiry_prepare(const char *refname,
cb->unreachable_expire_kind = UE_HEAD;
} else {
commit = lookup_commit(the_repository, oid);
+ if (commit && is_null_oid(&commit->object.oid))
+ commit = NULL;
cb->unreachable_expire_kind = commit ? UE_NORMAL : UE_ALWAYS;
}
diff --git a/sequencer.c b/sequencer.c
index 84eed9e96b..a1bb39383d 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -3749,7 +3749,7 @@ static int do_merge(struct repository *r,
int run_commit_flags = 0;
struct strbuf ref_name = STRBUF_INIT;
struct commit *head_commit, *merge_commit, *i;
- struct commit_list *bases, *j, *reversed = NULL;
+ struct commit_list *bases, *j;
struct commit_list *to_merge = NULL, **tail = &to_merge;
const char *strategy = !opts->xopts_nr &&
(!opts->strategy ||
@@ -3984,9 +3984,7 @@ static int do_merge(struct repository *r,
git_path_merge_head(r), 0);
write_message("no-ff", 5, git_path_merge_mode(r), 0);
- for (j = bases; j; j = j->next)
- commit_list_insert(j->item, &reversed);
- free_commit_list(bases);
+ bases = reverse_commit_list(bases);
repo_read_index(r);
init_merge_options(&o, r);
@@ -4002,10 +4000,10 @@ static int do_merge(struct repository *r,
* update the index and working copy immediately.
*/
ret = merge_ort_recursive(&o,
- head_commit, merge_commit, reversed,
+ head_commit, merge_commit, bases,
&i);
} else {
- ret = merge_recursive(&o, head_commit, merge_commit, reversed,
+ ret = merge_recursive(&o, head_commit, merge_commit, bases,
&i);
}
if (ret <= 0)
diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c
index 3da8525ce6..f3b90aa834 100644
--- a/t/helper/test-run-command.c
+++ b/t/helper/test-run-command.c
@@ -19,7 +19,6 @@
#include "thread-utils.h"
#include "wildmatch.h"
#include "gettext.h"
-#include "parse-options.h"
static int number_callbacks;
static int parallel_next(struct child_process *cp,
diff --git a/t/perf/p1006-cat-file.sh b/t/perf/p1006-cat-file.sh
new file mode 100755
index 0000000000..dcd8015379
--- /dev/null
+++ b/t/perf/p1006-cat-file.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+test_description='Tests listing object info performance'
+. ./perf-lib.sh
+
+test_perf_large_repo
+
+test_perf 'cat-file --batch-check' '
+ git cat-file --batch-all-objects --batch-check
+'
+
+test_done
diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh
index f17abd298c..1e864cf317 100755
--- a/t/t0410-partial-clone.sh
+++ b/t/t0410-partial-clone.sh
@@ -618,6 +618,25 @@ test_expect_success 'do not fetch when checking existence of tree we construct o
git -C repo cherry-pick side1
'
+test_expect_success 'exact rename does not need to fetch the blob lazily' '
+ rm -rf repo partial.git &&
+ test_create_repo repo &&
+ content="some dummy content" &&
+ test_commit -C repo create-a-file file.txt "$content" &&
+ git -C repo mv file.txt new-file.txt &&
+ git -C repo commit -m rename-the-file &&
+ FILE_HASH=$(git -C repo rev-parse HEAD:new-file.txt) &&
+ test_config -C repo uploadpack.allowfilter 1 &&
+ test_config -C repo uploadpack.allowanysha1inwant 1 &&
+
+ git clone --filter=blob:none --bare "file://$(pwd)/repo" partial.git &&
+ git -C partial.git rev-list --objects --missing=print HEAD >out &&
+ grep "[?]$FILE_HASH" out &&
+ git -C partial.git log --follow -- new-file.txt &&
+ git -C partial.git rev-list --objects --missing=print HEAD >out &&
+ grep "[?]$FILE_HASH" out
+'
+
test_expect_success 'lazy-fetch when accessing object not in the_repository' '
rm -rf full partial.git &&
test_create_repo full &&
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index 68f69bb543..ea8e6ac2a0 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -423,4 +423,13 @@ test_expect_success 'expire with multiple worktrees' '
)
'
+test_expect_success REFFILES 'empty reflog' '
+ test_when_finished "rm -rf empty" &&
+ git init empty &&
+ test_commit -C empty A &&
+ >empty/.git/logs/refs/heads/foo &&
+ git -C empty reflog expire --all 2>err &&
+ test_must_be_empty err
+'
+
test_done
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index 9babf13bc9..f3e20dd5bb 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -6,6 +6,8 @@
test_description='Test special whitespace in diff engine.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-diff.sh
@@ -1622,7 +1624,7 @@ test_expect_success 'cmd option assumes configured colored-moved' '
test_cmp expected actual
'
-test_expect_success 'no effect from --color-moved with --word-diff' '
+test_expect_success 'no effect on diff from --color-moved with --word-diff' '
cat <<-\EOF >text.txt &&
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
EOF
@@ -1636,6 +1638,12 @@ test_expect_success 'no effect from --color-moved with --word-diff' '
test_cmp expect actual
'
+test_expect_success !SANITIZE_LEAK 'no effect on show from --color-moved with --word-diff' '
+ git show --color-moved --word-diff >actual &&
+ git show --word-diff >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'set up whitespace tests' '
git reset --hard &&
# Note that these lines have no leading or trailing whitespace.
@@ -2016,7 +2024,7 @@ test_expect_success '--color-moved rewinds for MIN_ALNUM_COUNT' '
test_cmp expected actual
'
-test_expect_success 'move detection with submodules' '
+test_expect_success !SANITIZE_LEAK 'move detection with submodules' '
test_create_repo bananas &&
echo ripe >bananas/recipe &&
git -C bananas add recipe &&
diff --git a/t/t4018/kotlin-class b/t/t4018/kotlin-class
new file mode 100644
index 0000000000..bb864f22e6
--- /dev/null
+++ b/t/t4018/kotlin-class
@@ -0,0 +1,5 @@
+class RIGHT {
+ //comment
+ //comment
+ return ChangeMe
+}
diff --git a/t/t4018/kotlin-enum-class b/t/t4018/kotlin-enum-class
new file mode 100644
index 0000000000..8885f908fd
--- /dev/null
+++ b/t/t4018/kotlin-enum-class
@@ -0,0 +1,5 @@
+enum class RIGHT{
+ // Left
+ // a comment
+ ChangeMe
+}
diff --git a/t/t4018/kotlin-fun b/t/t4018/kotlin-fun
new file mode 100644
index 0000000000..2a60280256
--- /dev/null
+++ b/t/t4018/kotlin-fun
@@ -0,0 +1,5 @@
+fun RIGHT(){
+ //a comment
+ //b comment
+ return ChangeMe()
+}
diff --git a/t/t4018/kotlin-inheritace-class b/t/t4018/kotlin-inheritace-class
new file mode 100644
index 0000000000..77376c1f05
--- /dev/null
+++ b/t/t4018/kotlin-inheritace-class
@@ -0,0 +1,5 @@
+open class RIGHT{
+ // a comment
+ // b comment
+ // ChangeMe
+}
diff --git a/t/t4018/kotlin-inline-class b/t/t4018/kotlin-inline-class
new file mode 100644
index 0000000000..7bf46dd8d4
--- /dev/null
+++ b/t/t4018/kotlin-inline-class
@@ -0,0 +1,5 @@
+value class RIGHT(Args){
+ // a comment
+ // b comment
+ ChangeMe
+}
diff --git a/t/t4018/kotlin-interface b/t/t4018/kotlin-interface
new file mode 100644
index 0000000000..f686ba7770
--- /dev/null
+++ b/t/t4018/kotlin-interface
@@ -0,0 +1,5 @@
+interface RIGHT{
+ //another comment
+ //another comment
+ //ChangeMe
+}
diff --git a/t/t4018/kotlin-nested-fun b/t/t4018/kotlin-nested-fun
new file mode 100644
index 0000000000..12186858cb
--- /dev/null
+++ b/t/t4018/kotlin-nested-fun
@@ -0,0 +1,9 @@
+class LEFT{
+ class CENTER{
+ fun RIGHT( a:Int){
+ //comment
+ //comment
+ ChangeMe
+ }
+ }
+}
diff --git a/t/t4018/kotlin-public-class b/t/t4018/kotlin-public-class
new file mode 100644
index 0000000000..9433fcc226
--- /dev/null
+++ b/t/t4018/kotlin-public-class
@@ -0,0 +1,5 @@
+public class RIGHT{
+ //comment1
+ //comment2
+ ChangeMe
+}
diff --git a/t/t4018/kotlin-sealed-class b/t/t4018/kotlin-sealed-class
new file mode 100644
index 0000000000..0efa4a4eaf
--- /dev/null
+++ b/t/t4018/kotlin-sealed-class
@@ -0,0 +1,5 @@
+sealed class RIGHT {
+ // a comment
+ // b comment
+ ChangeMe
+}
diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh
index d5abcf4b4c..15764ee9ac 100755
--- a/t/t4034-diff-words.sh
+++ b/t/t4034-diff-words.sh
@@ -324,6 +324,7 @@ test_language_driver dts
test_language_driver fortran
test_language_driver html
test_language_driver java
+test_language_driver kotlin
test_language_driver matlab
test_language_driver objc
test_language_driver pascal
diff --git a/t/t4034/kotlin/expect b/t/t4034/kotlin/expect
new file mode 100644
index 0000000000..7f76f7540d
--- /dev/null
+++ b/t/t4034/kotlin/expect
@@ -0,0 +1,43 @@
+<BOLD>diff --git a/pre b/post<RESET>
+<BOLD>index 11ea3de..2e1df4c 100644<RESET>
+<BOLD>--- a/pre<RESET>
+<BOLD>+++ b/post<RESET>
+<CYAN>@@ -1,30 +1,30 @@<RESET>
+println("Hello World<RED>!\n<RESET><GREEN>?<RESET>")
+<GREEN>(<RESET>1<GREEN>) (<RESET>-1e10<GREEN>) (<RESET>0xabcdef<GREEN>)<RESET> '<RED>x<RESET><GREEN>y<RESET>'
+[<RED>a<RESET><GREEN>x<RESET>] <RED>a<RESET><GREEN>x<RESET>-><RED>b a<RESET><GREEN>y x<RESET>.<RED>b<RESET><GREEN>y<RESET>
+!<RED>a a<RESET><GREEN>x x<RESET>.inv() <RED>a<RESET><GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>&<RED>b<RESET>
+<RED>a<RESET><GREEN>y<RESET>
+<GREEN>x<RESET>*<RED>b a<RESET><GREEN>y x<RESET>/<RED>b a<RESET><GREEN>y x<RESET>%<RED>b<RESET>
+<RED>a<RESET><GREEN>y<RESET>
+<GREEN>x<RESET>+<RED>b a<RESET><GREEN>y x<RESET>-<RED>b<RESET><GREEN>y<RESET>
+a <RED>shr<RESET><GREEN>shl<RESET> b
+<RED>a<RESET><GREEN>x<RESET><<RED>b a<RESET><GREEN>y x<RESET><=<RED>b a<RESET><GREEN>y x<RESET>><RED>b a<RESET><GREEN>y x<RESET>>=<RED>b<RESET>
+<RED>a<RESET><GREEN>y<RESET>
+<GREEN>x<RESET>==<RED>b a<RESET><GREEN>y x<RESET>!=<RED>b a<RESET><GREEN>y x<RESET>===<RED>b<RESET>
+<RED>a<RESET><GREEN>y<RESET>
+<GREEN>x<RESET> and <RED>b<RESET>
+<RED>a<RESET><GREEN>y<RESET>
+<GREEN>x<RESET>^<RED>b<RESET>
+<RED>a<RESET><GREEN>y<RESET>
+<GREEN>x<RESET> or <RED>b<RESET>
+<RED>a<RESET><GREEN>y<RESET>
+<GREEN>x<RESET>&&<RED>b a<RESET><GREEN>y x<RESET>||<RED>b<RESET>
+<RED>a<RESET><GREEN>y<RESET>
+<GREEN>x<RESET>=<RED>b a<RESET><GREEN>y x<RESET>+=<RED>b a<RESET><GREEN>y x<RESET>-=<RED>b a<RESET><GREEN>y x<RESET>*=<RED>b a<RESET><GREEN>y x<RESET>/=<RED>b a<RESET><GREEN>y x<RESET>%=<RED>b a<RESET><GREEN>y x<RESET><<=<RED>b a<RESET><GREEN>y x<RESET>>>=<RED>b a<RESET><GREEN>y x<RESET>&=<RED>b a<RESET><GREEN>y x<RESET>^=<RED>b a<RESET><GREEN>y x<RESET>|=<RED>b<RESET><GREEN>y<RESET>
+a<RED>=<RESET><GREEN>+=<RESET>b c<RED>+=<RESET><GREEN>=<RESET>d e<RED>-=<RESET><GREEN><=<RESET>f g<RED>*=<RESET><GREEN>>=<RESET>h i<RED>/=<RESET><GREEN>/<RESET>j k<RED>%=<RESET><GREEN>%<RESET>l m<RED><<=<RESET><GREEN><<<RESET>n o<RED>>>=<RESET><GREEN>>><RESET>p q<RED>&=<RESET><GREEN>&<RESET>r s<RED>^=<RESET><GREEN>^<RESET>t u<RED>|=<RESET><GREEN>|<RESET>v
+a<RED><<=<RESET><GREEN><=<RESET>b
+a<RED>||<RESET><GREEN>|<RESET>b a<RED>&&<RESET><GREEN>&<RESET>b
+<RED>a<RESET><GREEN>x<RESET>,y
+--a<RED>==<RESET><GREEN>!=<RESET>--b
+a++<RED>==<RESET><GREEN>!=<RESET>++b
+<RED>0xFF_EC_DE_5E 0b100_000 100_000<RESET><GREEN>0xFF_E1_DE_5E 0b100_100 200_000<RESET>
+a<RED>==<RESET><GREEN>===<RESET>b
+a<RED>!!<RESET><GREEN>!=<RESET>b
+<RED>_32<RESET><GREEN>_33<RESET>.find(arr)
+X.<RED>fill<RESET><GREEN>find<RESET>()
+X.<RED>u<RESET><GREEN>f<RESET>+1
+X.u<RED>-<RESET><GREEN>+<RESET>2
+a<RED>.<RESET><GREEN>..<RESET>b
+a<RED>?.<RESET><GREEN>?:<RESET>b
+<RED>.32_00_456<RESET><GREEN>.32_00_446<RESET>
diff --git a/t/t4034/kotlin/post b/t/t4034/kotlin/post
new file mode 100644
index 0000000000..2e1df4c6d5
--- /dev/null
+++ b/t/t4034/kotlin/post
@@ -0,0 +1,30 @@
+println("Hello World?")
+(1) (-1e10) (0xabcdef) 'y'
+[x] x->y x.y
+!x x.inv() x*y x&y
+x*y x/y x%y
+x+y x-y
+a shl b
+x<y x<=y x>y x>=y
+x==y x!=y x===y
+x and y
+x^y
+x or y
+x&&y x||y
+x=y x+=y x-=y x*=y x/=y x%=y x<<=y x>>=y x&=y x^=y x|=y
+a+=b c=d e<=f g>=h i/j k%l m<<n o>>p q&r s^t u|v
+a<=b
+a|b a&b
+x,y
+--a!=--b
+a++!=++b
+0xFF_E1_DE_5E 0b100_100 200_000
+a===b
+a!=b
+_33.find(arr)
+X.find()
+X.f+1
+X.u+2
+a..b
+a?:b
+.32_00_446
diff --git a/t/t4034/kotlin/pre b/t/t4034/kotlin/pre
new file mode 100644
index 0000000000..11ea3de665
--- /dev/null
+++ b/t/t4034/kotlin/pre
@@ -0,0 +1,30 @@
+println("Hello World!\n")
+1 -1e10 0xabcdef 'x'
+[a] a->b a.b
+!a a.inv() a*b a&b
+a*b a/b a%b
+a+b a-b
+a shr b
+a<b a<=b a>b a>=b
+a==b a!=b a===b
+a and b
+a^b
+a or b
+a&&b a||b
+a=b a+=b a-=b a*=b a/=b a%=b a<<=b a>>=b a&=b a^=b a|=b
+a=b c+=d e-=f g*=h i/=j k%=l m<<=n o>>=p q&=r s^=t u|=v
+a<<=b
+a||b a&&b
+a,y
+--a==--b
+a++==++b
+0xFF_EC_DE_5E 0b100_000 100_000
+a==b
+a!!b
+_32.find(arr)
+X.fill()
+X.u+1
+X.u-2
+a.b
+a?.b
+.32_00_456
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 9781b92aed..9a35e783a7 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -488,6 +488,124 @@ test_expect_success 'name-rev covers all conditions while looking at parents' '
)
'
+# A-B-C-D-E-main
+#
+# Where C has a non-monotonically increasing commit timestamp w.r.t. other
+# commits
+test_expect_success 'non-monotonic commit dates setup' '
+ UNIX_EPOCH_ZERO="@0 +0000" &&
+ git init non-monotonic &&
+ test_commit -C non-monotonic A &&
+ test_commit -C non-monotonic --no-tag B &&
+ test_commit -C non-monotonic --no-tag --date "$UNIX_EPOCH_ZERO" C &&
+ test_commit -C non-monotonic D &&
+ test_commit -C non-monotonic E
+'
+
+test_expect_success 'name-rev with commitGraph handles non-monotonic timestamps' '
+ test_config -C non-monotonic core.commitGraph true &&
+ (
+ cd non-monotonic &&
+
+ git commit-graph write --reachable &&
+
+ echo "main~3 tags/D~2" >expect &&
+ git name-rev --tags main~3 >actual &&
+
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'name-rev --all works with non-monotonic timestamps' '
+ test_config -C non-monotonic core.commitGraph false &&
+ (
+ cd non-monotonic &&
+
+ rm -rf .git/info/commit-graph* &&
+
+ cat >tags <<-\EOF &&
+ tags/E
+ tags/D
+ tags/D~1
+ tags/D~2
+ tags/A
+ EOF
+
+ git log --pretty=%H >revs &&
+
+ paste -d" " revs tags | sort >expect &&
+
+ git name-rev --tags --all | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'name-rev --annotate-stdin works with non-monotonic timestamps' '
+ test_config -C non-monotonic core.commitGraph false &&
+ (
+ cd non-monotonic &&
+
+ rm -rf .git/info/commit-graph* &&
+
+ cat >expect <<-\EOF &&
+ E
+ D
+ D~1
+ D~2
+ A
+ EOF
+
+ git log --pretty=%H >revs &&
+ git name-rev --tags --annotate-stdin --name-only <revs >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'name-rev --all works with commitGraph' '
+ test_config -C non-monotonic core.commitGraph true &&
+ (
+ cd non-monotonic &&
+
+ git commit-graph write --reachable &&
+
+ cat >tags <<-\EOF &&
+ tags/E
+ tags/D
+ tags/D~1
+ tags/D~2
+ tags/A
+ EOF
+
+ git log --pretty=%H >revs &&
+
+ paste -d" " revs tags | sort >expect &&
+
+ git name-rev --tags --all | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'name-rev --annotate-stdin works with commitGraph' '
+ test_config -C non-monotonic core.commitGraph true &&
+ (
+ cd non-monotonic &&
+
+ git commit-graph write --reachable &&
+
+ cat >expect <<-\EOF &&
+ E
+ D
+ D~1
+ D~2
+ A
+ EOF
+
+ git log --pretty=%H >revs &&
+ git name-rev --tags --annotate-stdin --name-only <revs >actual &&
+ test_cmp expect actual
+ )
+'
+
# B
# o
# \
diff --git a/t/t6423-merge-rename-directories.sh b/t/t6423-merge-rename-directories.sh
index 5b81a130e9..479db32cd6 100755
--- a/t/t6423-merge-rename-directories.sh
+++ b/t/t6423-merge-rename-directories.sh
@@ -4421,14 +4421,14 @@ test_setup_12c1 () {
git checkout A &&
git mv node2/ node1/ &&
- for i in `git ls-files`; do echo side A >>$i; done &&
+ for i in $(git ls-files); do echo side A >>$i; done &&
git add -u &&
test_tick &&
git commit -m "A" &&
git checkout B &&
git mv node1/ node2/ &&
- for i in `git ls-files`; do echo side B >>$i; done &&
+ for i in $(git ls-files); do echo side B >>$i; done &&
git add -u &&
test_tick &&
git commit -m "B"
@@ -4511,7 +4511,7 @@ test_setup_12c2 () {
git checkout A &&
git mv node2/ node1/ &&
- for i in `git ls-files`; do echo side A >>$i; done &&
+ for i in $(git ls-files); do echo side A >>$i; done &&
git add -u &&
echo leaf5 >node1/leaf5 &&
git add node1/leaf5 &&
@@ -4520,7 +4520,7 @@ test_setup_12c2 () {
git checkout B &&
git mv node1/ node2/ &&
- for i in `git ls-files`; do echo side B >>$i; done &&
+ for i in $(git ls-files); do echo side B >>$i; done &&
git add -u &&
echo leaf6 >node2/leaf6 &&
git add node2/leaf6 &&
@@ -4759,7 +4759,7 @@ test_setup_12f () {
echo g >dir/subdir/tweaked/g &&
echo h >dir/subdir/tweaked/h &&
test_seq 20 30 >dir/subdir/tweaked/Makefile &&
- for i in `test_seq 1 88`; do
+ for i in $(test_seq 1 88); do
echo content $i >dir/unchanged/file_$i
done &&
git add . &&
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 11cccbb333..000e055811 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -205,8 +205,18 @@ test_expect_success 'submodule update should fail due to local changes' '
(cd submodule &&
compare_head
) &&
- test_must_fail git submodule update submodule
- )
+ test_must_fail git submodule update submodule 2>../actual.raw
+ ) &&
+ sed "s/^> //" >expect <<-\EOF &&
+ > error: Your local changes to the following files would be overwritten by checkout:
+ > file
+ > Please commit your changes or stash them before you switch branches.
+ > Aborting
+ > fatal: Unable to checkout OID in submodule path '\''submodule'\''
+ EOF
+ sed -e "s/checkout $SQ[^$SQ]*$SQ/checkout OID/" <actual.raw >actual &&
+ test_cmp expect actual
+
'
test_expect_success 'submodule update should throw away changes with --force ' '
(cd super &&
@@ -1061,4 +1071,16 @@ test_expect_success 'submodule update --quiet passes quietness to fetch with a s
)
'
+test_expect_success 'submodule update --filter requires --init' '
+ test_expect_code 129 git -C super submodule update --filter blob:none
+'
+
+test_expect_success 'submodule update --filter sets partial clone settings' '
+ test_when_finished "rm -rf super-filter" &&
+ git clone cloned super-filter &&
+ git -C super-filter submodule update --init --filter blob:none &&
+ test_cmp_config -C super-filter/submodule true remote.origin.promisor &&
+ test_cmp_config -C super-filter/submodule blob:none remote.origin.partialclonefilter
+'
+
test_done
diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh
index a3892f494b..c3a4545510 100755
--- a/t/t7408-submodule-reference.sh
+++ b/t/t7408-submodule-reference.sh
@@ -193,7 +193,19 @@ test_expect_success 'missing nested submodule alternate fails clone and submodul
cd supersuper-clone &&
check_that_two_of_three_alternates_are_used &&
# update of the submodule fails
- test_must_fail git submodule update --init --recursive
+ cat >expect <<-\EOF &&
+ fatal: submodule '\''sub'\'' cannot add alternate: path ... does not exist
+ Failed to clone '\''sub'\''. Retry scheduled
+ fatal: submodule '\''sub-dissociate'\'' cannot add alternate: path ... does not exist
+ Failed to clone '\''sub-dissociate'\''. Retry scheduled
+ fatal: submodule '\''sub'\'' cannot add alternate: path ... does not exist
+ Failed to clone '\''sub'\'' a second time, aborting
+ fatal: Failed to recurse into submodule path ...
+ EOF
+ test_must_fail git submodule update --init --recursive 2>err &&
+ grep -e fatal: -e ^Failed err >actual.raw &&
+ sed -e "s/path $SQ[^$SQ]*$SQ/path .../" <actual.raw >actual &&
+ test_cmp expect actual
)
'
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index 5922fb5bdd..770d143204 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -381,4 +381,54 @@ test_expect_success TTY '--quiet disables progress' '
test_must_be_empty stderr
'
+test_expect_success 'setup for update-server-info' '
+ git init update-server-info &&
+ test_commit -C update-server-info message
+'
+
+test_server_info_present () {
+ test_path_is_file update-server-info/.git/objects/info/packs &&
+ test_path_is_file update-server-info/.git/info/refs
+}
+
+test_server_info_missing () {
+ test_path_is_missing update-server-info/.git/objects/info/packs &&
+ test_path_is_missing update-server-info/.git/info/refs
+}
+
+test_server_info_cleanup () {
+ rm -f update-server-info/.git/objects/info/packs update-server-info/.git/info/refs &&
+ test_server_info_missing
+}
+
+test_expect_success 'updates server info by default' '
+ test_server_info_cleanup &&
+ git -C update-server-info repack &&
+ test_server_info_present
+'
+
+test_expect_success '-n skips updating server info' '
+ test_server_info_cleanup &&
+ git -C update-server-info repack -n &&
+ test_server_info_missing
+'
+
+test_expect_success 'repack.updateServerInfo=true updates server info' '
+ test_server_info_cleanup &&
+ git -C update-server-info -c repack.updateServerInfo=true repack &&
+ test_server_info_present
+'
+
+test_expect_success 'repack.updateServerInfo=false skips updating server info' '
+ test_server_info_cleanup &&
+ git -C update-server-info -c repack.updateServerInfo=false repack &&
+ test_server_info_missing
+'
+
+test_expect_success '-n overrides repack.updateServerInfo=true' '
+ test_server_info_cleanup &&
+ git -C update-server-info -c repack.updateServerInfo=true repack -n &&
+ test_server_info_missing
+'
+
test_done
diff --git a/userdiff.c b/userdiff.c
index 2d9eb99bf2..151d9a5278 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -180,6 +180,18 @@ PATTERNS("java",
"|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
"|[-+*/<>%&^|=!]="
"|--|\\+\\+|<<=?|>>>?=?|&&|\\|\\|"),
+PATTERNS("kotlin",
+ "^[ \t]*(([a-z]+[ \t]+)*(fun|class|interface)[ \t]+.*)$",
+ /* -- */
+ "[a-zA-Z_][a-zA-Z0-9_]*"
+ /* hexadecimal and binary numbers */
+ "|0[xXbB][0-9a-fA-F_]+[lLuU]*"
+ /* integers and floats */
+ "|[0-9][0-9_]*([.][0-9_]*)?([Ee][-+]?[0-9]+)?[fFlLuU]*"
+ /* floating point numbers beginning with decimal point */
+ "|[.][0-9][0-9_]*([Ee][-+]?[0-9]+)?[fFlLuU]?"
+ /* unary and binary operators */
+ "|[-+*/<>%&^|=!]==?|--|\\+\\+|<<=|>>=|&&|\\|\\||->|\\.\\*|!!|[?:.][.:]"),
PATTERNS("markdown",
"^ {0,3}#{1,6}[ \t].*",
/* -- */