Merge branch 'master' of git://repo.or.cz/alt-git

This commit is contained in:
Johannes Sixt
2010-02-08 08:19:55 +01:00
73 changed files with 3917 additions and 2868 deletions

View File

@@ -38,7 +38,7 @@ Notes on behaviour change
whitespaces is reported with zero exit status when run with
--exit-code, and there is no "diff --git" header for such a change.
* external diff and textconv helpers are now executed using the shell.
* External diff and textconv helpers are now executed using the shell.
This makes them consistent with other programs executed by git, and
allows you to pass command-line parameters to the helpers. Any helper
paths containing spaces or other metacharacters now need to be
@@ -46,6 +46,12 @@ Notes on behaviour change
environment, and diff.*.command and diff.*.textconv in the config
file.
* The --max-pack-size argument to 'git repack', 'git pack-objects', and
'git fast-import' was assuming the provided size to be expressed in MiB,
unlike the corresponding config variable and other similar options accepting
a size value. It is now expecting a size expressed in bytes, with a possible
unit suffix of 'k', 'm', or 'g'.
Updates since v1.6.6
--------------------
@@ -59,6 +65,8 @@ Updates since v1.6.6
* "gitk" updates.
* "gitweb" updates (code clean-up, load checking etc.)
(portability)
* Some more MSVC portability patches for msysgit port.
@@ -127,9 +135,6 @@ Updates since v1.6.6
* "git grep" does not rely on external grep anymore. It can use more than
one threads to accelerate the operation.
* "git grep" learned "--no-index" option, to search inside contents that
are not managed by git.
* "git grep" learned "--quiet" option.
* "git log" and friends learned "--glob=heads/*" syntax that is a more
@@ -200,14 +205,19 @@ release, unless otherwise noted.
from non-root dir, 2010-01-26) may be merged to older maintenance
branches.
* When "git diff" is asked to compare the work tree with something,
it used to consider that a checked-out submodule with uncommitted
changes is not modified; this could cause people to forget committing
these changes in the submodule before committing in the superproject.
It now considers such a change as a modification.
* "git fast-import" did not correctly handle large blobs that may
bust the pack size limit.
* When using "git status" or asking "git diff" to compare the work tree
with something, they used to consider that a checked-out submodule with
uncommitted changes is not modified; this could cause people to forget
committing these changes in the submodule before committing in the
superproject. They now consider such a change as a modification and
"git diff" will append a "-dirty" to the work tree side when generating
patch output or when used with the --submodule option.
--
exec >/var/tmp/1
O=v1.7.0-rc1-6-g2ee8c5b
O=v1.7.0-rc1-42-g3bd8de5
echo O=$(git describe master)
git shortlog --no-merges $O..master ^maint

View File

@@ -417,6 +417,20 @@ You probably do not need to adjust this value.
+
Common unit suffixes of 'k', 'm', or 'g' are supported.
core.bigFileThreshold::
Files larger than this size are stored deflated, without
attempting delta compression. Storing large files without
delta compression avoids excessive memory usage, at the
slight expense of increased disk usage.
+
Default is 512 MiB on all platforms. This should be reasonable
for most projects as source code and other text files can still
be delta compressed, but larger binary media files won't be.
+
Common unit suffixes of 'k', 'm', or 'g' are supported.
+
Currently only linkgit:git-fast-import[1] honors this setting.
core.excludesfile::
In addition to '.gitignore' (per-directory) and
'.git/info/exclude', git looks into this file for patterns
@@ -1354,10 +1368,13 @@ you can use linkgit:git-index-pack[1] on the *.pack file to regenerate
the `{asterisk}.idx` file.
pack.packSizeLimit::
The default maximum size of a pack. This setting only affects
packing to a file, i.e. the git:// protocol is unaffected. It
can be overridden by the `\--max-pack-size` option of
linkgit:git-repack[1].
The maximum size of a pack. This setting only affects
packing to a file when repacking, i.e. the git:// protocol
is unaffected. It can be overridden by the `\--max-pack-size`
option of linkgit:git-repack[1]. The minimum size allowed is
limited to 1 MiB. The default is unlimited.
Common unit suffixes of 'k', 'm', or 'g' are
supported.
pager.<cmd>::
Allows turning on or off pagination of the output of a

View File

@@ -33,8 +33,8 @@ OPTIONS
-f::
--force::
If the git configuration specifies clean.requireForce as true,
'git clean' will refuse to run unless given -f or -n.
If the git configuration variable clean.requireForce is not set
to false, 'git clean' will refuse to run unless given -f or -n.
-n::
--dry-run::

View File

@@ -44,12 +44,18 @@ OPTIONS
not contain the old commit).
--max-pack-size=<n>::
Maximum size of each output packfile, expressed in MiB.
The default is 4096 (4 GiB) as that is the maximum allowed
Maximum size of each output packfile.
The default is 4 GiB as that is the maximum allowed
packfile size (due to file format limitations). Some
importers may wish to lower this, such as to ensure the
resulting packfiles fit on CDs.
--big-file-threshold=<n>::
Maximum size of a blob that fast-import will attempt to
create a delta for, expressed in bytes. The default is 512m
(512 MiB). Some importers may wish to lower this on systems
with constrained memory.
--depth=<n>::
Maximum delta depth, for blob and tree deltification.
Default is 10.

View File

@@ -358,7 +358,7 @@ To move the whole tree into a subdirectory, or remove it from there:
---------------------------------------------------------------
git filter-branch --index-filter \
'git ls-files -s | sed "s-\t-&newsubdir/-" |
'git ls-files -s | sed "s-\t\"*-&newsubdir/-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' HEAD

View File

@@ -105,8 +105,9 @@ base-name::
`--window-memory=0` makes memory usage unlimited, which is the
default.
--max-pack-size=<n>::
Maximum size of each output packfile, expressed in MiB.
--max-pack-size=[N]::
Maximum size of each output pack file. The size can be suffixed with
"k", "m", or "g". The minimum size allowed is limited to 1 MiB.
If specified, multiple packfiles may be created.
The default is unlimited, unless the config variable
`pack.packSizeLimit` is set.

View File

@@ -98,24 +98,26 @@ other objects in that pack they already have locally.
`--window-memory=0` makes memory usage unlimited, which is the
default.
--max-pack-size=<n>::
Maximum size of each output packfile, expressed in MiB.
--max-pack-size=[N]::
Maximum size of each output pack file. The size can be suffixed with
"k", "m", or "g". The minimum size allowed is limited to 1 MiB.
If specified, multiple packfiles may be created.
The default is unlimited.
The default is unlimited, unless the config variable
`pack.packSizeLimit` is set.
Configuration
-------------
When configuration variable `repack.UseDeltaBaseOffset` is set
for the repository, the command passes `--delta-base-offset`
option to 'git pack-objects'; this typically results in slightly
smaller packs, but the generated packs are incompatible with
versions of git older than (and including) v1.4.3; do not set
the variable in a repository that older version of git needs to
be able to read (this includes repositories from which packs can
be copied out over http or rsync, and people who obtained packs
that way can try to use older git with it).
By default, the command passes `--delta-base-offset` option to
'git pack-objects'; this typically results in slightly smaller packs,
but the generated packs are incompatible with versions of Git older than
version 1.4.4. If you need to share your repository with such ancient Git
versions, either directly or via the dumb http or rsync protocol, then you
need to set the configuration variable `repack.UseDeltaBaseOffset` to
"false" and repack. Access from old Git versions over the native protocol
is unaffected by this option as the conversion is performed on the fly
as needed in that case.
Author

View File

@@ -3640,6 +3640,26 @@ Did you forget to 'git add'?
Unable to checkout '261dfac35cb99d380eb966e102c1197139f7fa24' in submodule path 'a'
-------------------------------------------------
In older git versions it could be easily forgotten to commit new or modified
files in a submodule, which silently leads to similar problems as not pushing
the submodule changes. Starting with git 1.7.0 both "git status" and "git diff"
in the superproject show submodules as modified when they contain new or
modified files to protect against accidentally committing such a state. "git
diff" will also add a "-dirty" to the work tree side when generating patch
output or used with the --submodule option:
-------------------------------------------------
$ git diff
diff --git a/sub b/sub
--- a/sub
+++ b/sub
@@ -1 +1 @@
-Subproject commit 3f356705649b5d566d97ff843cf193359229a453
+Subproject commit 3f356705649b5d566d97ff843cf193359229a453-dirty
$ git diff --submodule
Submodule sub 3f35670..3f35670-dirty:
-------------------------------------------------
You also should not rewind branches in a submodule beyond commits that were
ever recorded in any superproject.

View File

@@ -275,29 +275,6 @@ pathsep = :
# JavaScript minifier invocation that can function as filter
JSMIN =
# default configuration for gitweb
GITWEB_CONFIG = gitweb_config.perl
GITWEB_CONFIG_SYSTEM = /etc/gitweb.conf
GITWEB_HOME_LINK_STR = projects
GITWEB_SITENAME =
GITWEB_PROJECTROOT = /pub/git
GITWEB_PROJECT_MAXDEPTH = 2007
GITWEB_EXPORT_OK =
GITWEB_STRICT_EXPORT =
GITWEB_BASE_URL =
GITWEB_LIST =
GITWEB_HOMETEXT = indextext.html
GITWEB_CSS = gitweb.css
GITWEB_LOGO = git-logo.png
GITWEB_FAVICON = git-favicon.png
ifdef JSMIN
GITWEB_JS = gitweb.min.js
else
GITWEB_JS = gitweb.js
endif
GITWEB_SITE_HEADER =
GITWEB_SITE_FOOTER =
export prefix bindir sharedir sysconfdir
CC = gcc
@@ -1518,6 +1495,11 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl
chmod +x $@+ && \
mv $@+ $@
.PHONY: gitweb
gitweb:
$(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) all
ifdef JSMIN
OTHER_PROGRAMS += gitweb/gitweb.cgi gitweb/gitweb.min.js
gitweb/gitweb.cgi: gitweb/gitweb.perl gitweb/gitweb.min.js
@@ -1525,30 +1507,13 @@ else
OTHER_PROGRAMS += gitweb/gitweb.cgi
gitweb/gitweb.cgi: gitweb/gitweb.perl
endif
$(QUIET_GEN)$(RM) $@ $@+ && \
sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \
-e 's|++GIT_VERSION++|$(GIT_VERSION)|g' \
-e 's|++GIT_BINDIR++|$(bindir)|g' \
-e 's|++GITWEB_CONFIG++|$(GITWEB_CONFIG)|g' \
-e 's|++GITWEB_CONFIG_SYSTEM++|$(GITWEB_CONFIG_SYSTEM)|g' \
-e 's|++GITWEB_HOME_LINK_STR++|$(GITWEB_HOME_LINK_STR)|g' \
-e 's|++GITWEB_SITENAME++|$(GITWEB_SITENAME)|g' \
-e 's|++GITWEB_PROJECTROOT++|$(GITWEB_PROJECTROOT)|g' \
-e 's|"++GITWEB_PROJECT_MAXDEPTH++"|$(GITWEB_PROJECT_MAXDEPTH)|g' \
-e 's|++GITWEB_EXPORT_OK++|$(GITWEB_EXPORT_OK)|g' \
-e 's|++GITWEB_STRICT_EXPORT++|$(GITWEB_STRICT_EXPORT)|g' \
-e 's|++GITWEB_BASE_URL++|$(GITWEB_BASE_URL)|g' \
-e 's|++GITWEB_LIST++|$(GITWEB_LIST)|g' \
-e 's|++GITWEB_HOMETEXT++|$(GITWEB_HOMETEXT)|g' \
-e 's|++GITWEB_CSS++|$(GITWEB_CSS)|g' \
-e 's|++GITWEB_LOGO++|$(GITWEB_LOGO)|g' \
-e 's|++GITWEB_FAVICON++|$(GITWEB_FAVICON)|g' \
-e 's|++GITWEB_JS++|$(GITWEB_JS)|g' \
-e 's|++GITWEB_SITE_HEADER++|$(GITWEB_SITE_HEADER)|g' \
-e 's|++GITWEB_SITE_FOOTER++|$(GITWEB_SITE_FOOTER)|g' \
$< >$@+ && \
chmod +x $@+ && \
mv $@+ $@
$(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) $(patsubst gitweb/%,%,$@)
ifdef JSMIN
gitweb/gitweb.min.js: gitweb/gitweb.js
$(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) $(patsubst gitweb/%,%,$@)
endif # JSMIN
git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css gitweb/gitweb.js
$(QUIET_GEN)$(RM) $@ $@+ && \
@@ -1575,12 +1540,6 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)) git-instaweb: % : unimplemented.sh
mv $@+ $@
endif # NO_PERL
ifdef JSMIN
gitweb/gitweb.min.js: gitweb/gitweb.js
$(QUIET_GEN)$(JSMIN) <$< >$@
endif # JSMIN
ifndef NO_PYTHON
$(patsubst %.py,%,$(SCRIPT_PYTHON)): GIT-CFLAGS
$(patsubst %.py,%,$(SCRIPT_PYTHON)): % : %.py

View File

@@ -70,7 +70,7 @@ static const char *format_from_name(const char *filename)
return NULL;
ext++;
if (!strcasecmp(ext, "zip"))
return "zip";
return "--format=zip";
return NULL;
}
@@ -84,7 +84,7 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
const char *exec = "git-upload-archive";
const char *output = NULL;
const char *remote = NULL;
const char *format = NULL;
const char *format_option = NULL;
struct option local_opts[] = {
OPT_STRING('o', "output", &output, "file",
"write the archive to this file"),
@@ -92,33 +92,31 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
"retrieve the archive from remote repository <repo>"),
OPT_STRING(0, "exec", &exec, "cmd",
"path to the remote git-upload-archive command"),
OPT_STRING(0, "format", &format, "fmt", "archive format"),
OPT_END()
};
char fmt_opt[32];
argc = parse_options(argc, argv, prefix, local_opts, NULL,
PARSE_OPT_KEEP_ALL);
if (output) {
create_output_file(output);
if (!format)
format = format_from_name(output);
format_option = format_from_name(output);
}
if (format) {
sprintf(fmt_opt, "--format=%s", format);
/*
* We have enough room in argv[] to muck it in place,
* because either --format and/or --output must have
* been given on the original command line if we get
* to this point, and parse_options() must have eaten
* it, i.e. we can add back one element to the array.
* But argv[] may contain "--"; we should make it the
* first option.
*/
/*
* We have enough room in argv[] to muck it in place, because
* --output must have been given on the original command line
* if we get to this point, and parse_options() must have eaten
* it, i.e. we can add back one element to the array.
*
* We add a fake --format option at the beginning, with the
* format inferred from our output filename. This way explicit
* --format options can override it, and the fake option is
* inserted before any "--" that might have been given.
*/
if (format_option) {
memmove(argv + 2, argv + 1, sizeof(*argv) * argc);
argv[1] = fmt_opt;
argv[1] = format_option;
argv[++argc] = NULL;
}

View File

@@ -67,8 +67,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
die("-x and -X cannot be used together");
if (!show_only && !force)
die("clean.requireForce%s set and -n or -f not given; "
"refusing to clean", config_set ? "" : " not");
die("clean.requireForce %s to true and neither -n nor -f given; "
"refusing to clean", config_set ? "set" : "defaults");
if (force > 1)
rm_flags = 0;

View File

@@ -578,7 +578,7 @@ static struct option fsck_opts[] = {
OPT_BOOLEAN(0, "root", &show_root, "report root nodes"),
OPT_BOOLEAN(0, "cache", &keep_cache_objects, "make index objects head nodes"),
OPT_BOOLEAN(0, "reflogs", &include_reflogs, "make reflogs head nodes (default)"),
OPT_BOOLEAN(0, "full", &check_full, "also consider alternate objects"),
OPT_BOOLEAN(0, "full", &check_full, "also consider packs and alternate objects"),
OPT_BOOLEAN(0, "strict", &check_strict, "enable more strict checking"),
OPT_BOOLEAN(0, "lost-found", &write_lost_and_found,
"write dangling objects in .git/lost-found"),

View File

@@ -14,7 +14,6 @@
#include "userdiff.h"
#include "grep.h"
#include "quote.h"
#include "dir.h"
#ifndef NO_PTHREADS
#include "thread-utils.h"
@@ -646,24 +645,6 @@ static int grep_object(struct grep_opt *opt, const char **paths,
die("unable to grep from object of type %s", typename(obj->type));
}
static int grep_directory(struct grep_opt *opt, const char **paths)
{
struct dir_struct dir;
int i, hit = 0;
memset(&dir, 0, sizeof(dir));
setup_standard_excludes(&dir);
fill_directory(&dir, paths);
for (i = 0; i < dir.nr; i++) {
hit |= grep_file(opt, dir.entries[i]->name);
if (hit && opt->status_only)
break;
}
free_grep_patterns(opt);
return hit;
}
static int context_callback(const struct option *opt, const char *arg,
int unset)
{
@@ -758,12 +739,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
const char **paths = NULL;
int i;
int dummy;
int nongit = 0, use_index = 1;
struct option options[] = {
OPT_BOOLEAN(0, "cached", &cached,
"search in index instead of in the work tree"),
OPT_BOOLEAN(0, "index", &use_index,
"--no-index finds in contents not managed by git"),
OPT_GROUP(""),
OPT_BOOLEAN('v', "invert-match", &opt.invert,
"show non-matching lines"),
@@ -846,8 +824,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
OPT_END()
};
prefix = setup_git_directory_gently(&nongit);
/*
* 'git grep -h', unlike 'git grep -h <pattern>', is a request
* to show usage information and exit.
@@ -885,10 +861,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
PARSE_OPT_STOP_AT_NON_OPTION |
PARSE_OPT_NO_INTERNAL_HELP);
if (use_index && nongit)
/* die the same way as if we did it at the beginning */
setup_git_directory();
/* First unrecognized non-option token */
if (argc > 0 && !opt.pattern_list) {
append_grep_pattern(&opt, argv[0], "command line", 0,
@@ -950,18 +922,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
paths[1] = NULL;
}
if (!use_index) {
int hit;
if (cached)
die("--cached cannot be used with --no-index.");
if (list.nr)
die("--no-index cannot be used with revs.");
hit = grep_directory(&opt, paths);
if (use_threads)
hit |= wait_all();
return !hit;
}
if (!list.nr) {
int hit;
if (!cached)

View File

@@ -77,7 +77,7 @@ static int allow_ofs_delta;
static const char *base_name;
static int progress = 1;
static int window = 10;
static uint32_t pack_size_limit, pack_size_limit_cfg;
static unsigned long pack_size_limit, pack_size_limit_cfg;
static int depth = 50;
static int delta_search_threads;
static int pack_to_stdout;
@@ -246,7 +246,7 @@ static unsigned long write_object(struct sha1file *f,
type = entry->type;
/* write limit if limited packsize and not first object */
/* apply size limit if limited packsize and not first object */
if (!pack_size_limit || !nr_written)
limit = 0;
else if (pack_size_limit <= write_offset)
@@ -443,11 +443,15 @@ static int write_one(struct sha1file *f,
/* offset is non zero if object is written already. */
if (e->idx.offset || e->preferred_base)
return 1;
return -1;
/* if we are deltified, write out base object first. */
if (e->delta && !write_one(f, e->delta, offset))
return 0;
/*
* If we are deltified, attempt to write out base object first.
* If that fails due to the pack size limit then the current
* object might still possibly fit undeltified within that limit.
*/
if (e->delta)
write_one(f, e->delta, offset);
e->idx.offset = *offset;
size = write_object(f, e, *offset);
@@ -501,11 +505,9 @@ static void write_pack_file(void)
sha1write(f, &hdr, sizeof(hdr));
offset = sizeof(hdr);
nr_written = 0;
for (; i < nr_objects; i++) {
if (!write_one(f, objects + i, &offset))
break;
display_progress(progress_state, written);
}
for (i = 0; i < nr_objects; i++)
if (write_one(f, objects + i, &offset) == 1)
display_progress(progress_state, written);
/*
* Did we write the wrong # entries in the header?
@@ -580,26 +582,13 @@ static void write_pack_file(void)
written_list[j]->offset = (off_t)-1;
}
nr_remaining -= nr_written;
} while (nr_remaining && i < nr_objects);
} while (nr_remaining);
free(written_list);
stop_progress(&progress_state);
if (written != nr_result)
die("wrote %"PRIu32" objects while expecting %"PRIu32,
written, nr_result);
/*
* We have scanned through [0 ... i). Since we have written
* the correct number of objects, the remaining [i ... nr_objects)
* items must be either already written (due to out-of-order delta base)
* or a preferred base. Count those which are neither and complain if any.
*/
for (j = 0; i < nr_objects; i++) {
struct object_entry *e = objects + i;
j += !e->idx.offset && !e->preferred_base;
}
if (j)
die("wrote %"PRIu32" objects as expected but %"PRIu32
" unwritten", written, j);
}
static int locate_object_entry_hash(const unsigned char *sha1)
@@ -2203,10 +2192,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
continue;
}
if (!prefixcmp(arg, "--max-pack-size=")) {
char *end;
pack_size_limit_cfg = 0;
pack_size_limit = strtoul(arg+16, &end, 0) * 1024 * 1024;
if (!arg[16] || *end)
if (!git_parse_ulong(arg+16, &pack_size_limit))
usage(pack_usage);
continue;
}
@@ -2346,9 +2333,12 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
if (!pack_to_stdout && !pack_size_limit)
pack_size_limit = pack_size_limit_cfg;
if (pack_to_stdout && pack_size_limit)
die("--max-pack-size cannot be used to build a pack for transfer.");
if (pack_size_limit && pack_size_limit < 1024*1024) {
warning("minimum pack size limit is 1 MiB");
pack_size_limit = 1024*1024;
}
if (!pack_to_stdout && thin)
die("--thin cannot be used to build an indexable pack.");

View File

@@ -23,21 +23,32 @@ AC_DEFUN([GIT_CONF_APPEND_LINE],
# GIT_ARG_SET_PATH(PROGRAM)
# -------------------------
# Provide --with-PROGRAM=PATH option to set PATH to PROGRAM
# Optional second argument allows setting NO_PROGRAM=YesPlease if
# --without-PROGRAM version used.
AC_DEFUN([GIT_ARG_SET_PATH],
[AC_ARG_WITH([$1],
[AS_HELP_STRING([--with-$1=PATH],
[provide PATH to $1])],
[GIT_CONF_APPEND_PATH($1)],[])
[GIT_CONF_APPEND_PATH($1,$2)],[])
])# GIT_ARG_SET_PATH
#
# GIT_CONF_APPEND_PATH(PROGRAM)
# ------------------------------
# Parse --with-PROGRAM=PATH option to set PROGRAM_PATH=PATH
# Used by GIT_ARG_SET_PATH(PROGRAM)
# Optional second argument allows setting NO_PROGRAM=YesPlease if
# --without-PROGRAM is used.
AC_DEFUN([GIT_CONF_APPEND_PATH],
[PROGRAM=m4_toupper($1); \
if test "$withval" = "no"; then \
AC_MSG_ERROR([You cannot use git without $1]); \
if test -n "$2"; then \
m4_toupper($1)_PATH=$withval; \
AC_MSG_NOTICE([Disabling use of ${PROGRAM}]); \
GIT_CONF_APPEND_LINE(NO_${PROGRAM}=YesPlease); \
GIT_CONF_APPEND_LINE(${PROGRAM}_PATH=); \
else \
AC_MSG_ERROR([You cannot use git without $1]); \
fi; \
else \
if test "$withval" = "yes"; then \
AC_MSG_WARN([You should provide path for --with-$1=PATH]); \
@@ -277,7 +288,7 @@ GIT_ARG_SET_PATH(shell)
GIT_ARG_SET_PATH(perl)
#
# Define PYTHON_PATH to provide path to Python.
GIT_ARG_SET_PATH(python)
GIT_ARG_SET_PATH(python, allow-without)
#
# Define ZLIB_PATH to provide path to zlib.
GIT_ARG_SET_PATH(zlib)

View File

@@ -1386,6 +1386,7 @@ _git_rebase ()
--preserve-merges --stat --no-stat
--committer-date-is-author-date --ignore-date
--ignore-whitespace --whitespace=
--autosquash
"
return

View File

@@ -1037,7 +1037,7 @@ class P4Sync(Command):
if includeFile:
filesForCommit.append(f)
if f['action'] not in ('delete', 'purge'):
if f['action'] not in ('delete', 'move/delete', 'purge'):
filesToRead.append(f)
else:
filesToDelete.append(f)

View File

@@ -281,6 +281,7 @@ struct recent_command
/* Configured limits on output */
static unsigned long max_depth = 10;
static off_t max_packsize = (1LL << 32) - 1;
static uintmax_t big_file_threshold = 512 * 1024 * 1024;
static int force_update;
static int pack_compression_level = Z_DEFAULT_COMPRESSION;
static int pack_compression_seen;
@@ -1014,7 +1015,7 @@ static void cycle_packfile(void)
static size_t encode_header(
enum object_type type,
size_t size,
uintmax_t size,
unsigned char *hdr)
{
int n = 1;
@@ -1170,6 +1171,118 @@ static int store_object(
return 0;
}
static void truncate_pack(off_t to)
{
if (ftruncate(pack_data->pack_fd, to)
|| lseek(pack_data->pack_fd, to, SEEK_SET) != to)
die_errno("cannot truncate pack to skip duplicate");
pack_size = to;
}
static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark)
{
size_t in_sz = 64 * 1024, out_sz = 64 * 1024;
unsigned char *in_buf = xmalloc(in_sz);
unsigned char *out_buf = xmalloc(out_sz);
struct object_entry *e;
unsigned char sha1[20];
unsigned long hdrlen;
off_t offset;
git_SHA_CTX c;
z_stream s;
int status = Z_OK;
/* Determine if we should auto-checkpoint. */
if ((pack_size + 60 + len) > max_packsize
|| (pack_size + 60 + len) < pack_size)
cycle_packfile();
offset = pack_size;
hdrlen = snprintf((char *)out_buf, out_sz, "blob %" PRIuMAX, len) + 1;
if (out_sz <= hdrlen)
die("impossibly large object header");
git_SHA1_Init(&c);
git_SHA1_Update(&c, out_buf, hdrlen);
memset(&s, 0, sizeof(s));
deflateInit(&s, pack_compression_level);
hdrlen = encode_header(OBJ_BLOB, len, out_buf);
if (out_sz <= hdrlen)
die("impossibly large object header");
s.next_out = out_buf + hdrlen;
s.avail_out = out_sz - hdrlen;
while (status != Z_STREAM_END) {
if (0 < len && !s.avail_in) {
size_t cnt = in_sz < len ? in_sz : (size_t)len;
size_t n = fread(in_buf, 1, cnt, stdin);
if (!n && feof(stdin))
die("EOF in data (%" PRIuMAX " bytes remaining)", len);
git_SHA1_Update(&c, in_buf, n);
s.next_in = in_buf;
s.avail_in = n;
len -= n;
}
status = deflate(&s, len ? 0 : Z_FINISH);
if (!s.avail_out || status == Z_STREAM_END) {
size_t n = s.next_out - out_buf;
write_or_die(pack_data->pack_fd, out_buf, n);
pack_size += n;
s.next_out = out_buf;
s.avail_out = out_sz;
}
switch (status) {
case Z_OK:
case Z_BUF_ERROR:
case Z_STREAM_END:
continue;
default:
die("unexpected deflate failure: %d", status);
}
}
deflateEnd(&s);
git_SHA1_Final(sha1, &c);
if (sha1out)
hashcpy(sha1out, sha1);
e = insert_object(sha1);
if (mark)
insert_mark(mark, e);
if (e->offset) {
duplicate_count_by_type[OBJ_BLOB]++;
truncate_pack(offset);
} else if (find_sha1_pack(sha1, packed_git)) {
e->type = OBJ_BLOB;
e->pack_id = MAX_PACK_ID;
e->offset = 1; /* just not zero! */
duplicate_count_by_type[OBJ_BLOB]++;
truncate_pack(offset);
} else {
e->depth = 0;
e->type = OBJ_BLOB;
e->pack_id = pack_id;
e->offset = offset;
object_count++;
object_count_by_type[OBJ_BLOB]++;
}
free(in_buf);
free(out_buf);
}
/* All calls must be guarded by find_object() or find_mark() to
* ensure the 'struct object_entry' passed was written by this
* process instance. We unpack the entry by the offset, avoiding
@@ -1757,7 +1870,7 @@ static void parse_mark(void)
next_mark = 0;
}
static void parse_data(struct strbuf *sb)
static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
{
strbuf_reset(sb);
@@ -1781,9 +1894,15 @@ static void parse_data(struct strbuf *sb)
free(term);
}
else {
size_t n = 0, length;
uintmax_t len = strtoumax(command_buf.buf + 5, NULL, 10);
size_t n = 0, length = (size_t)len;
length = strtoul(command_buf.buf + 5, NULL, 10);
if (limit && limit < len) {
*len_res = len;
return 0;
}
if (length < len)
die("data is too large to use in this context");
while (n < length) {
size_t s = strbuf_fread(sb, length - n, stdin);
@@ -1795,6 +1914,7 @@ static void parse_data(struct strbuf *sb)
}
skip_optional_lf();
return 1;
}
static int validate_raw_date(const char *src, char *result, int maxlen)
@@ -1859,14 +1979,32 @@ static char *parse_ident(const char *buf)
return ident;
}
static void parse_new_blob(void)
static void parse_and_store_blob(
struct last_object *last,
unsigned char *sha1out,
uintmax_t mark)
{
static struct strbuf buf = STRBUF_INIT;
uintmax_t len;
if (parse_data(&buf, big_file_threshold, &len))
store_object(OBJ_BLOB, &buf, last, sha1out, mark);
else {
if (last) {
strbuf_release(&last->data);
last->offset = 0;
last->depth = 0;
}
stream_blob(len, sha1out, mark);
skip_optional_lf();
}
}
static void parse_new_blob(void)
{
read_next_command();
parse_mark();
parse_data(&buf);
store_object(OBJ_BLOB, &buf, &last_blob, NULL, next_mark);
parse_and_store_blob(&last_blob, NULL, next_mark);
}
static void unload_one_branch(void)
@@ -2080,15 +2218,12 @@ static void file_change_m(struct branch *b)
* another repository.
*/
} else if (inline_data) {
static struct strbuf buf = STRBUF_INIT;
if (p != uq.buf) {
strbuf_addstr(&uq, p);
p = uq.buf;
}
read_next_command();
parse_data(&buf);
store_object(OBJ_BLOB, &buf, &last_blob, sha1, 0);
parse_and_store_blob(&last_blob, sha1, 0);
} else if (oe) {
if (oe->type != OBJ_BLOB)
die("Not a blob (actually a %s): %s",
@@ -2216,15 +2351,12 @@ static void note_change_n(struct branch *b, unsigned char old_fanout)
die("Invalid ref name or SHA1 expression: %s", p);
if (inline_data) {
static struct strbuf buf = STRBUF_INIT;
if (p != uq.buf) {
strbuf_addstr(&uq, p);
p = uq.buf;
}
read_next_command();
parse_data(&buf);
store_object(OBJ_BLOB, &buf, &last_blob, sha1, 0);
parse_and_store_blob(&last_blob, sha1, 0);
} else if (oe) {
if (oe->type != OBJ_BLOB)
die("Not a blob (actually a %s): %s",
@@ -2401,7 +2533,7 @@ static void parse_new_commit(void)
}
if (!committer)
die("Expected committer but didn't get one");
parse_data(&msg);
parse_data(&msg, 0, NULL);
read_next_command();
parse_from(b);
merge_list = parse_merge(&merge_count);
@@ -2528,7 +2660,7 @@ static void parse_new_tag(void)
tagger = NULL;
/* tag payload/message */
parse_data(&msg);
parse_data(&msg, 0, NULL);
/* build the tag object */
strbuf_reset(&new_data);
@@ -2632,11 +2764,6 @@ static void option_date_format(const char *fmt)
die("unknown --date-format argument %s", fmt);
}
static void option_max_pack_size(const char *packsize)
{
max_packsize = strtoumax(packsize, NULL, 0) * 1024 * 1024;
}
static void option_depth(const char *depth)
{
max_depth = strtoul(depth, NULL, 0);
@@ -2666,7 +2793,22 @@ static void option_export_pack_edges(const char *edges)
static int parse_one_option(const char *option)
{
if (!prefixcmp(option, "max-pack-size=")) {
option_max_pack_size(option + 14);
unsigned long v;
if (!git_parse_ulong(option + 14, &v))
return 0;
if (v < 8192) {
warning("max-pack-size is now in bytes, assuming --max-pack-size=%lum", v);
v *= 1024 * 1024;
} else if (v < 1024 * 1024) {
warning("minimum max-pack-size is 1 MiB");
v = 1024 * 1024;
}
max_packsize = v;
} else if (!prefixcmp(option, "big-file-threshold=")) {
unsigned long v;
if (!git_parse_ulong(option + 19, &v))
return 0;
big_file_threshold = v;
} else if (!prefixcmp(option, "depth=")) {
option_depth(option + 6);
} else if (!prefixcmp(option, "active-branches=")) {
@@ -2749,11 +2891,15 @@ static int git_pack_config(const char *k, const char *v, void *cb)
pack_compression_seen = 1;
return 0;
}
if (!strcmp(k, "core.bigfilethreshold")) {
long n = git_config_int(k, v);
big_file_threshold = 0 < n ? n : 0;
}
return git_default_config(k, v, cb);
}
static const char fast_import_usage[] =
"git fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
"git fast-import [--date-format=f] [--max-pack-size=n] [--big-file-threshold=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
static void parse_argv(void)
{

View File

@@ -331,7 +331,7 @@ while read commit parents; do
die "tree filter failed: $filter_tree"
(
git diff-index -r --name-only $commit &&
git diff-index -r --name-only --ignore-submodules $commit &&
git ls-files --others
) > "$tempdir"/tree-state || exit
git update-index --add --replace --remove --stdin \

View File

@@ -121,6 +121,8 @@ unset oguimsg
set _appname {Git Gui}
set _gitdir {}
set _gitworktree {}
set _isbare {}
set _gitexec {}
set _githtmldir {}
set _reponame {}
@@ -276,6 +278,32 @@ proc get_config {name} {
}
}
proc is_bare {} {
global _isbare
global _gitdir
global _gitworktree
if {$_isbare eq {}} {
if {[catch {
set _bare [git rev-parse --is-bare-repository]
switch -- $_bare {
true { set _isbare 1 }
false { set _isbare 0}
default { throw }
}
}]} {
if {[is_config_true core.bare]
|| ($_gitworktree eq {}
&& [lindex [file split $_gitdir] end] ne {.git})} {
set _isbare 1
} else {
set _isbare 0
}
}
}
return $_isbare
}
######################################################################
##
## handy utils
@@ -649,12 +677,17 @@ if {[is_Windows]} {
## config defaults
set cursor_ptr arrow
font create font_diff -family Courier -size 10
font create font_ui
catch {
label .dummy
eval font configure font_ui [font actual [.dummy cget -font]]
destroy .dummy
if {[lsearch -exact [font names] TkDefaultFont] != -1} {
eval [linsert [font actual TkDefaultFont] 0 font configure font_ui]
eval [linsert [font actual TkFixedFont] 0 font create font_diff]
} else {
font create font_diff -family Courier -size 10
catch {
label .dummy
eval font configure font_ui [font actual [.dummy cget -font]]
destroy .dummy
}
}
font create font_uiitalic
@@ -669,6 +702,9 @@ foreach class {Button Checkbutton Entry Label
}
if {![is_MacOSX]} {
option add *Menu.font font_ui
option add *Entry.borderWidth 1 startupFile
option add *Entry.relief sunken startupFile
option add *RadioButton.anchor w startupFile
}
unset class
@@ -721,6 +757,18 @@ proc apply_config {} {
font configure ${font}bold -weight bold
font configure ${font}italic -slant italic
}
global use_ttk NS
set use_ttk 0
set NS {}
if {$repo_config(gui.usettk)} {
set use_ttk [package vsatisfies [package provide Tk] 8.5]
if {$use_ttk} {
set NS ttk
bind [winfo class .] <<ThemeChanged>> [list InitTheme]
pave_toplevel .
}
}
}
set default_config(branch.autosetupmerge) true
@@ -747,6 +795,7 @@ set default_config(gui.fontui) [font configure font_ui]
set default_config(gui.fontdiff) [font configure font_diff]
# TODO: this option should be added to the git-config documentation
set default_config(gui.maxfilesdisplayed) 5000
set default_config(gui.usettk) 1
set font_descs {
{fontui font_ui {mc "Main Font"}}
{fontdiff font_diff {mc "Diff/Console Font"}}
@@ -1100,25 +1149,41 @@ if {![file isdirectory $_gitdir]} {
error_popup [strcat [mc "Git directory not found:"] "\n\n$_gitdir"]
exit 1
}
# _gitdir exists, so try loading the config
load_config 0
apply_config
# try to set work tree from environment, falling back to core.worktree
if {[catch { set _gitworktree $env(GIT_WORK_TREE) }]} {
set _gitworktree [get_config core.worktree]
}
if {$_prefix ne {}} {
regsub -all {[^/]+/} $_prefix ../ cdup
if {$_gitworktree eq {}} {
regsub -all {[^/]+/} $_prefix ../ cdup
} else {
set cdup $_gitworktree
}
if {[catch {cd $cdup} err]} {
catch {wm withdraw .}
error_popup [strcat [mc "Cannot move to top of working directory:"] "\n\n$err"]
exit 1
}
set _gitworktree [pwd]
unset cdup
} elseif {![is_enabled bare]} {
if {[lindex [file split $_gitdir] end] ne {.git}} {
if {[is_bare]} {
catch {wm withdraw .}
error_popup [strcat [mc "Cannot use funny .git directory:"] "\n\n$_gitdir"]
error_popup [strcat [mc "Cannot use bare repository:"] "\n\n$_gitdir"]
exit 1
}
if {[catch {cd [file dirname $_gitdir]} err]} {
if {$_gitworktree eq {}} {
set _gitworktree [file dirname $_gitdir]
}
if {[catch {cd $_gitworktree} err]} {
catch {wm withdraw .}
error_popup [strcat [mc "No working directory"] " [file dirname $_gitdir]:\n\n$err"]
error_popup [strcat [mc "No working directory"] " $_gitworktree:\n\n$err"]
exit 1
}
set _gitworktree [pwd]
}
set _reponame [file split [file normalize $_gitdir]]
if {[lindex $_reponame end] eq {.git}} {
@@ -1127,6 +1192,9 @@ if {[lindex $_reponame end] eq {.git}} {
set _reponame [lindex $_reponame end]
}
set env(GIT_DIR) $_gitdir
set env(GIT_WORK_TREE) $_gitworktree
######################################################################
##
## global init
@@ -1808,15 +1876,6 @@ static unsigned char file_fulltick_bits[] = {
0x62, 0x10, 0x02, 0x10, 0xfe, 0x1f};
} -maskdata $filemask
image create bitmap file_parttick -background white -foreground "#005050" -data {
#define parttick_width 14
#define parttick_height 15
static unsigned char parttick_bits[] = {
0xfe, 0x01, 0x02, 0x03, 0x7a, 0x05, 0x02, 0x09, 0x7a, 0x1f, 0x02, 0x10,
0x7a, 0x14, 0x02, 0x16, 0x02, 0x13, 0x8a, 0x11, 0xda, 0x10, 0x72, 0x10,
0x22, 0x10, 0x02, 0x10, 0xfe, 0x1f};
} -maskdata $filemask
image create bitmap file_question -background white -foreground black -data {
#define file_question_width 14
#define file_question_height 15
@@ -1857,7 +1916,7 @@ set ui_index .vpane.files.index.list
set ui_workdir .vpane.files.workdir.list
set all_icons(_$ui_index) file_plain
set all_icons(A$ui_index) file_fulltick
set all_icons(A$ui_index) file_plain
set all_icons(M$ui_index) file_fulltick
set all_icons(D$ui_index) file_removed
set all_icons(U$ui_index) file_merge
@@ -1933,7 +1992,10 @@ proc incr_font_size {font {amt 1}} {
set starting_gitk_msg [mc "Starting gitk... please wait..."]
proc do_gitk {revs} {
proc do_gitk {revs {is_submodule false}} {
global current_diff_path file_states current_diff_side ui_index
global _gitdir _gitworktree
# -- Always start gitk through whatever we were loaded with. This
# lets us bypass using shell process on Windows systems.
#
@@ -1944,23 +2006,78 @@ proc do_gitk {revs} {
} else {
global env
if {[info exists env(GIT_DIR)]} {
set old_GIT_DIR $env(GIT_DIR)
} else {
set old_GIT_DIR {}
}
set pwd [pwd]
cd [file dirname [gitdir]]
set env(GIT_DIR) [file tail [gitdir]]
if {!$is_submodule} {
if {![is_bare]} {
cd $_gitworktree
}
} else {
cd $current_diff_path
if {$revs eq {--}} {
set s $file_states($current_diff_path)
set old_sha1 {}
set new_sha1 {}
switch -glob -- [lindex $s 0] {
M_ { set old_sha1 [lindex [lindex $s 2] 1] }
_M { set old_sha1 [lindex [lindex $s 3] 1] }
MM {
if {$current_diff_side eq $ui_index} {
set old_sha1 [lindex [lindex $s 2] 1]
set new_sha1 [lindex [lindex $s 3] 1]
} else {
set old_sha1 [lindex [lindex $s 3] 1]
}
}
}
set revs $old_sha1...$new_sha1
}
# GIT_DIR and GIT_WORK_TREE for the submodule are not the ones
# we've been using for the main repository, so unset them.
# TODO we could make life easier (start up faster?) for gitk
# by setting these to the appropriate values to allow gitk
# to skip the heuristics to find their proper value
unset env(GIT_DIR)
unset env(GIT_WORK_TREE)
}
eval exec $cmd $revs "--" "--" &
if {$old_GIT_DIR eq {}} {
unset env(GIT_DIR)
} else {
set env(GIT_DIR) $old_GIT_DIR
set env(GIT_DIR) $_gitdir
set env(GIT_WORK_TREE) $_gitworktree
cd $pwd
ui_status $::starting_gitk_msg
after 10000 {
ui_ready $starting_gitk_msg
}
}
}
proc do_git_gui {} {
global current_diff_path
# -- Always start git gui through whatever we were loaded with. This
# lets us bypass using shell process on Windows systems.
#
set exe [list [_which git]]
if {$exe eq {}} {
error_popup [mc "Couldn't find git gui in PATH"]
} else {
global env
global _gitdir _gitworktree
# see note in do_gitk about unsetting these vars when
# running tools in a submodule
unset env(GIT_DIR)
unset env(GIT_WORK_TREE)
set pwd [pwd]
cd $current_diff_path
eval exec $exe gui &
set env(GIT_DIR) $_gitdir
set env(GIT_WORK_TREE) $_gitworktree
cd $pwd
ui_status $::starting_gitk_msg
@@ -1971,6 +2088,7 @@ proc do_gitk {revs} {
}
proc do_explore {} {
global _gitworktree
set explorer {}
if {[is_Cygwin] || [is_Windows]} {
set explorer "explorer.exe"
@@ -1980,7 +2098,7 @@ proc do_explore {} {
# freedesktop.org-conforming system is our best shot
set explorer "xdg-open"
}
eval exec $explorer [list [file nativename [file dirname [gitdir]]]] &
eval exec $explorer $_gitworktree &
}
set is_quitting 0
@@ -1996,7 +2114,7 @@ proc do_quit {{rc {1}}} {
global ui_comm is_quitting repo_config commit_type
global GITGUI_BCK_exists GITGUI_BCK_i
global ui_comm_spell
global ret_code
global ret_code use_ttk
if {$is_quitting} return
set is_quitting 1
@@ -2054,8 +2172,13 @@ proc do_quit {{rc {1}}} {
}
set cfg_geometry [list]
lappend cfg_geometry [wm geometry .]
lappend cfg_geometry [lindex [.vpane sash coord 0] 0]
lappend cfg_geometry [lindex [.vpane.files sash coord 0] 1]
if {$use_ttk} {
lappend cfg_geometry [.vpane sashpos 0]
lappend cfg_geometry [.vpane.files sashpos 0]
} else {
lappend cfg_geometry [lindex [.vpane sash coord 0] 0]
lappend cfg_geometry [lindex [.vpane.files sash coord 0] 1]
}
if {[catch {set rc_geometry $repo_config(gui.geometry)}]} {
set rc_geometry {}
}
@@ -2344,8 +2467,6 @@ proc show_less_context {} {
##
## ui construction
load_config 0
apply_config
set ui_comm {}
# -- Menu Bar
@@ -2377,10 +2498,12 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} {
#
menu .mbar.repository
.mbar.repository add command \
-label [mc "Explore Working Copy"] \
-command {do_explore}
.mbar.repository add separator
if {![is_bare]} {
.mbar.repository add command \
-label [mc "Explore Working Copy"] \
-command {do_explore}
.mbar.repository add separator
}
.mbar.repository add command \
-label [mc "Browse Current Branch's Files"] \
@@ -2822,14 +2945,13 @@ default {
# -- Branch Control
#
frame .branch \
-borderwidth 1 \
-relief sunken
label .branch.l1 \
${NS}::frame .branch
if {!$use_ttk} {.branch configure -borderwidth 1 -relief sunken}
${NS}::label .branch.l1 \
-text [mc "Current Branch:"] \
-anchor w \
-justify left
label .branch.cb \
${NS}::label .branch.cb \
-textvariable current_branch \
-anchor w \
-justify left
@@ -2839,15 +2961,20 @@ pack .branch -side top -fill x
# -- Main Window Layout
#
panedwindow .vpane -orient horizontal
panedwindow .vpane.files -orient vertical
.vpane add .vpane.files -sticky nsew -height 100 -width 200
${NS}::panedwindow .vpane -orient horizontal
${NS}::panedwindow .vpane.files -orient vertical
if {$use_ttk} {
.vpane add .vpane.files
} else {
.vpane add .vpane.files -sticky nsew -height 100 -width 200
}
pack .vpane -anchor n -side top -fill both -expand 1
# -- Index File List
#
frame .vpane.files.index -height 100 -width 200
label .vpane.files.index.title -text [mc "Staged Changes (Will Commit)"] \
${NS}::frame .vpane.files.index -height 100 -width 200
tlabel .vpane.files.index.title \
-text [mc "Staged Changes (Will Commit)"] \
-background lightgreen -foreground black
text $ui_index -background white -foreground black \
-borderwidth 0 \
@@ -2857,8 +2984,8 @@ text $ui_index -background white -foreground black \
-xscrollcommand {.vpane.files.index.sx set} \
-yscrollcommand {.vpane.files.index.sy set} \
-state disabled
scrollbar .vpane.files.index.sx -orient h -command [list $ui_index xview]
scrollbar .vpane.files.index.sy -orient v -command [list $ui_index yview]
${NS}::scrollbar .vpane.files.index.sx -orient h -command [list $ui_index xview]
${NS}::scrollbar .vpane.files.index.sy -orient v -command [list $ui_index yview]
pack .vpane.files.index.title -side top -fill x
pack .vpane.files.index.sx -side bottom -fill x
pack .vpane.files.index.sy -side right -fill y
@@ -2866,8 +2993,8 @@ pack $ui_index -side left -fill both -expand 1
# -- Working Directory File List
#
frame .vpane.files.workdir -height 100 -width 200
label .vpane.files.workdir.title -text [mc "Unstaged Changes"] \
${NS}::frame .vpane.files.workdir -height 100 -width 200
tlabel .vpane.files.workdir.title -text [mc "Unstaged Changes"] \
-background lightsalmon -foreground black
text $ui_workdir -background white -foreground black \
-borderwidth 0 \
@@ -2877,15 +3004,19 @@ text $ui_workdir -background white -foreground black \
-xscrollcommand {.vpane.files.workdir.sx set} \
-yscrollcommand {.vpane.files.workdir.sy set} \
-state disabled
scrollbar .vpane.files.workdir.sx -orient h -command [list $ui_workdir xview]
scrollbar .vpane.files.workdir.sy -orient v -command [list $ui_workdir yview]
${NS}::scrollbar .vpane.files.workdir.sx -orient h -command [list $ui_workdir xview]
${NS}::scrollbar .vpane.files.workdir.sy -orient v -command [list $ui_workdir yview]
pack .vpane.files.workdir.title -side top -fill x
pack .vpane.files.workdir.sx -side bottom -fill x
pack .vpane.files.workdir.sy -side right -fill y
pack $ui_workdir -side left -fill both -expand 1
.vpane.files add .vpane.files.workdir -sticky nsew
.vpane.files add .vpane.files.index -sticky nsew
.vpane.files add .vpane.files.workdir
.vpane.files add .vpane.files.index
if {!$use_ttk} {
.vpane.files paneconfigure .vpane.files.workdir -sticky news
.vpane.files paneconfigure .vpane.files.index -sticky news
}
foreach i [list $ui_index $ui_workdir] {
rmsel_tag $i
@@ -2895,68 +3026,69 @@ unset i
# -- Diff and Commit Area
#
frame .vpane.lower -height 300 -width 400
frame .vpane.lower.commarea
frame .vpane.lower.diff -relief sunken -borderwidth 1
${NS}::frame .vpane.lower -height 300 -width 400
${NS}::frame .vpane.lower.commarea
${NS}::frame .vpane.lower.diff -relief sunken -borderwidth 1
pack .vpane.lower.diff -fill both -expand 1
pack .vpane.lower.commarea -side bottom -fill x
.vpane add .vpane.lower -sticky nsew
.vpane add .vpane.lower
if {!$use_ttk} {.vpane paneconfigure .vpane.lower -sticky nsew}
# -- Commit Area Buttons
#
frame .vpane.lower.commarea.buttons
label .vpane.lower.commarea.buttons.l -text {} \
${NS}::frame .vpane.lower.commarea.buttons
${NS}::label .vpane.lower.commarea.buttons.l -text {} \
-anchor w \
-justify left
pack .vpane.lower.commarea.buttons.l -side top -fill x
pack .vpane.lower.commarea.buttons -side left -fill y
button .vpane.lower.commarea.buttons.rescan -text [mc Rescan] \
${NS}::button .vpane.lower.commarea.buttons.rescan -text [mc Rescan] \
-command ui_do_rescan
pack .vpane.lower.commarea.buttons.rescan -side top -fill x
lappend disable_on_lock \
{.vpane.lower.commarea.buttons.rescan conf -state}
button .vpane.lower.commarea.buttons.incall -text [mc "Stage Changed"] \
${NS}::button .vpane.lower.commarea.buttons.incall -text [mc "Stage Changed"] \
-command do_add_all
pack .vpane.lower.commarea.buttons.incall -side top -fill x
lappend disable_on_lock \
{.vpane.lower.commarea.buttons.incall conf -state}
if {![is_enabled nocommitmsg]} {
button .vpane.lower.commarea.buttons.signoff -text [mc "Sign Off"] \
${NS}::button .vpane.lower.commarea.buttons.signoff -text [mc "Sign Off"] \
-command do_signoff
pack .vpane.lower.commarea.buttons.signoff -side top -fill x
}
button .vpane.lower.commarea.buttons.commit -text [commit_btn_caption] \
${NS}::button .vpane.lower.commarea.buttons.commit -text [commit_btn_caption] \
-command do_commit
pack .vpane.lower.commarea.buttons.commit -side top -fill x
lappend disable_on_lock \
{.vpane.lower.commarea.buttons.commit conf -state}
if {![is_enabled nocommit]} {
button .vpane.lower.commarea.buttons.push -text [mc Push] \
${NS}::button .vpane.lower.commarea.buttons.push -text [mc Push] \
-command do_push_anywhere
pack .vpane.lower.commarea.buttons.push -side top -fill x
}
# -- Commit Message Buffer
#
frame .vpane.lower.commarea.buffer
frame .vpane.lower.commarea.buffer.header
${NS}::frame .vpane.lower.commarea.buffer
${NS}::frame .vpane.lower.commarea.buffer.header
set ui_comm .vpane.lower.commarea.buffer.t
set ui_coml .vpane.lower.commarea.buffer.header.l
if {![is_enabled nocommit]} {
radiobutton .vpane.lower.commarea.buffer.header.new \
${NS}::radiobutton .vpane.lower.commarea.buffer.header.new \
-text [mc "New Commit"] \
-command do_select_commit_type \
-variable selected_commit_type \
-value new
lappend disable_on_lock \
[list .vpane.lower.commarea.buffer.header.new conf -state]
radiobutton .vpane.lower.commarea.buffer.header.amend \
${NS}::radiobutton .vpane.lower.commarea.buffer.header.amend \
-text [mc "Amend Last Commit"] \
-command do_select_commit_type \
-variable selected_commit_type \
@@ -2965,7 +3097,7 @@ if {![is_enabled nocommit]} {
[list .vpane.lower.commarea.buffer.header.amend conf -state]
}
label $ui_coml \
${NS}::label $ui_coml \
-anchor w \
-justify left
proc trace_commit_type {varname args} {
@@ -2997,7 +3129,7 @@ text $ui_comm -background white -foreground black \
-width $repo_config(gui.commitmsgwidth) -height 9 -wrap none \
-font font_diff \
-yscrollcommand {.vpane.lower.commarea.buffer.sby set}
scrollbar .vpane.lower.commarea.buffer.sby \
${NS}::scrollbar .vpane.lower.commarea.buffer.sby \
-command [list $ui_comm yview]
pack .vpane.lower.commarea.buffer.header -side top -fill x
pack .vpane.lower.commarea.buffer.sby -side right -fill y
@@ -3063,19 +3195,19 @@ proc trace_current_diff_path {varname args} {
}
trace add variable current_diff_path write trace_current_diff_path
frame .vpane.lower.diff.header -background gold
label .vpane.lower.diff.header.status \
gold_frame .vpane.lower.diff.header
tlabel .vpane.lower.diff.header.status \
-background gold \
-foreground black \
-width $max_status_desc \
-anchor w \
-justify left
label .vpane.lower.diff.header.file \
tlabel .vpane.lower.diff.header.file \
-background gold \
-foreground black \
-anchor w \
-justify left
label .vpane.lower.diff.header.path \
tlabel .vpane.lower.diff.header.path \
-background gold \
-foreground black \
-anchor w \
@@ -3099,7 +3231,7 @@ bind_button3 .vpane.lower.diff.header.path "tk_popup $ctxm %X %Y"
# -- Diff Body
#
frame .vpane.lower.diff.body
${NS}::frame .vpane.lower.diff.body
set ui_diff .vpane.lower.diff.body.t
text $ui_diff -background white -foreground black \
-borderwidth 0 \
@@ -3108,9 +3240,9 @@ text $ui_diff -background white -foreground black \
-xscrollcommand {.vpane.lower.diff.body.sbx set} \
-yscrollcommand {.vpane.lower.diff.body.sby set} \
-state disabled
scrollbar .vpane.lower.diff.body.sbx -orient horizontal \
${NS}::scrollbar .vpane.lower.diff.body.sbx -orient horizontal \
-command [list $ui_diff xview]
scrollbar .vpane.lower.diff.body.sby -orient vertical \
${NS}::scrollbar .vpane.lower.diff.body.sby -orient vertical \
-command [list $ui_diff yview]
pack .vpane.lower.diff.body.sbx -side bottom -fill x
pack .vpane.lower.diff.body.sby -side right -fill y
@@ -3154,15 +3286,6 @@ $ui_diff tag raise sel
#
proc create_common_diff_popup {ctxm} {
$ctxm add command \
-label [mc "Show Less Context"] \
-command show_less_context
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
$ctxm add command \
-label [mc "Show More Context"] \
-command show_more_context
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
$ctxm add separator
$ctxm add command \
-label [mc Refresh] \
-command reshow_diff
@@ -3214,10 +3337,19 @@ set ui_diff_applyhunk [$ctxm index last]
lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state]
$ctxm add command \
-label [mc "Apply/Reverse Line"] \
-command {apply_line $cursorX $cursorY; do_rescan}
-command {apply_range_or_line $cursorX $cursorY; do_rescan}
set ui_diff_applyline [$ctxm index last]
lappend diff_actions [list $ctxm entryconf $ui_diff_applyline -state]
$ctxm add separator
$ctxm add command \
-label [mc "Show Less Context"] \
-command show_less_context
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
$ctxm add command \
-label [mc "Show More Context"] \
-command show_more_context
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
$ctxm add separator
create_common_diff_popup $ctxm
set ctxmmg .vpane.lower.diff.body.ctxmmg
@@ -3240,9 +3372,40 @@ $ctxmmg add command \
-command {merge_resolve_one 1}
lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
$ctxmmg add separator
$ctxmmg add command \
-label [mc "Show Less Context"] \
-command show_less_context
lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
$ctxmmg add command \
-label [mc "Show More Context"] \
-command show_more_context
lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
$ctxmmg add separator
create_common_diff_popup $ctxmmg
proc popup_diff_menu {ctxm ctxmmg x y X Y} {
set ctxmsm .vpane.lower.diff.body.ctxmsm
menu $ctxmsm -tearoff 0
$ctxmsm add command \
-label [mc "Visualize These Changes In The Submodule"] \
-command {do_gitk -- true}
lappend diff_actions [list $ctxmsm entryconf [$ctxmsm index last] -state]
$ctxmsm add command \
-label [mc "Visualize Current Branch History In The Submodule"] \
-command {do_gitk {} true}
lappend diff_actions [list $ctxmsm entryconf [$ctxmsm index last] -state]
$ctxmsm add command \
-label [mc "Visualize All Branch History In The Submodule"] \
-command {do_gitk --all true}
lappend diff_actions [list $ctxmsm entryconf [$ctxmsm index last] -state]
$ctxmsm add separator
$ctxmsm add command \
-label [mc "Start git gui In The Submodule"] \
-command {do_git_gui}
lappend diff_actions [list $ctxmsm entryconf [$ctxmsm index last] -state]
$ctxmsm add separator
create_common_diff_popup $ctxmsm
proc popup_diff_menu {ctxm ctxmmg ctxmsm x y X Y} {
global current_diff_path file_states
set ::cursorX $x
set ::cursorY $y
@@ -3253,15 +3416,26 @@ proc popup_diff_menu {ctxm ctxmmg x y X Y} {
}
if {[string first {U} $state] >= 0} {
tk_popup $ctxmmg $X $Y
} elseif {$::is_submodule_diff} {
tk_popup $ctxmsm $X $Y
} else {
set has_range [expr {[$::ui_diff tag nextrange sel 0.0] != {}}]
if {$::ui_index eq $::current_diff_side} {
set l [mc "Unstage Hunk From Commit"]
set t [mc "Unstage Line From Commit"]
if {$has_range} {
set t [mc "Unstage Lines From Commit"]
} else {
set t [mc "Unstage Line From Commit"]
}
} else {
set l [mc "Stage Hunk For Commit"]
set t [mc "Stage Line For Commit"]
if {$has_range} {
set t [mc "Stage Lines For Commit"]
} else {
set t [mc "Stage Line For Commit"]
}
}
if {$::is_3way_diff || $::is_submodule_diff
if {$::is_3way_diff
|| $current_diff_path eq {}
|| {__} eq $state
|| {_O} eq $state
@@ -3276,7 +3450,7 @@ proc popup_diff_menu {ctxm ctxmmg x y X Y} {
tk_popup $ctxm $X $Y
}
}
bind_button3 $ui_diff [list popup_diff_menu $ctxm $ctxmmg %x %y %X %Y]
bind_button3 $ui_diff [list popup_diff_menu $ctxm $ctxmmg $ctxmsm %x %y %X %Y]
# -- Status Bar
#
@@ -3289,12 +3463,17 @@ $main_status show [mc "Initializing..."]
catch {
set gm $repo_config(gui.geometry)
wm geometry . [lindex $gm 0]
.vpane sash place 0 \
[lindex $gm 1] \
[lindex [.vpane sash coord 0] 1]
.vpane.files sash place 0 \
[lindex [.vpane.files sash coord 0] 0] \
[lindex $gm 2]
if {$use_ttk} {
.vpane sashpos 0 [lindex $gm 1]
.vpane.files sashpos 0 [lindex $gm 2]
} else {
.vpane sash place 0 \
[lindex $gm 1] \
[lindex [.vpane sash coord 0] 1]
.vpane.files sash place 0 \
[lindex [.vpane.files sash coord 0] 0] \
[lindex $gm 2]
}
unset gm
}
@@ -3371,6 +3550,8 @@ bind . <$M1B-Key-s> do_signoff
bind . <$M1B-Key-S> do_signoff
bind . <$M1B-Key-t> do_add_selection
bind . <$M1B-Key-T> do_add_selection
bind . <$M1B-Key-j> do_revert_selection
bind . <$M1B-Key-J> do_revert_selection
bind . <$M1B-Key-i> do_add_all
bind . <$M1B-Key-I> do_add_all
bind . <$M1B-Key-minus> {show_less_context;break}
@@ -3389,7 +3570,7 @@ unset i
set file_lists($ui_index) [list]
set file_lists($ui_workdir) [list]
wm title . "[appname] ([reponame]) [file normalize [file dirname [gitdir]]]"
wm title . "[appname] ([reponame]) [file normalize $_gitworktree]"
focus -force $ui_comm
# -- Warn the user about environmental problems. Cygwin's Tcl
@@ -3562,3 +3743,9 @@ if {[is_enabled retcode]} {
if {$picked && [is_config_true gui.autoexplore]} {
do_explore
}
# Local variables:
# mode: tcl
# indent-tabs-mode: t
# tab-width: 4
# End:

View File

@@ -4,31 +4,26 @@
proc do_about {} {
global appvers copyright oguilib
global tcl_patchLevel tk_patchLevel
global ui_comm_spell
global ui_comm_spell NS use_ttk
set w .about_dialog
toplevel $w
Dialog $w
wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
pack [git_logo $w.git_logo] -side left -fill y -padx 10 -pady 10
label $w.header -text [mc "About %s" [appname]] \
-font font_uibold
${NS}::label $w.header -text [mc "About %s" [appname]] \
-font font_uibold -anchor center
pack $w.header -side top -fill x
frame $w.buttons
button $w.buttons.close -text {Close} \
${NS}::frame $w.buttons
${NS}::button $w.buttons.close -text {Close} \
-default active \
-command [list destroy $w]
pack $w.buttons.close -side right
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
label $w.desc \
-text "[mc "git-gui - a graphical user interface for Git."]\n$copyright" \
-padx 5 -pady 5 \
-justify left \
-anchor w \
-borderwidth 1 \
-relief solid
paddedlabel $w.desc \
-text "[mc "git-gui - a graphical user interface for Git."]\n$copyright"
pack $w.desc -side top -fill x -padx 5 -pady 5
set v {}
@@ -52,22 +47,10 @@ proc do_about {} {
append d "git exec dir: [gitexec]\n"
append d "git-gui lib: $oguilib"
label $w.vers \
-text $v \
-padx 5 -pady 5 \
-justify left \
-anchor w \
-borderwidth 1 \
-relief solid
paddedlabel $w.vers -text $v
pack $w.vers -side top -fill x -padx 5 -pady 5
label $w.dirs \
-text $d \
-padx 5 -pady 5 \
-justify left \
-anchor w \
-borderwidth 1 \
-relief solid
paddedlabel $w.dirs -text $d
pack $w.dirs -side top -fill x -padx 5 -pady 5
menu $w.ctxm -tearoff 0

View File

@@ -61,7 +61,7 @@ field tooltip_timer {} ; # Current timer event for our tooltip
field tooltip_commit {} ; # Commit(s) in tooltip
constructor new {i_commit i_path i_jump} {
global cursor_ptr M1B M1T have_tk85
global cursor_ptr M1B M1T have_tk85 use_ttk NS
variable active_color
variable group_colors
@@ -73,15 +73,15 @@ constructor new {i_commit i_path i_jump} {
set font_w [font measure font_diff "0"]
frame $w.header -background gold
label $w.header.commit_l \
gold_frame $w.header
tlabel $w.header.commit_l \
-text [mc "Commit:"] \
-background gold \
-foreground black \
-anchor w \
-justify left
set w_back $w.header.commit_b
label $w_back \
tlabel $w_back \
-image ::blame::img_back_arrow \
-borderwidth 0 \
-relief flat \
@@ -94,20 +94,20 @@ constructor new {i_commit i_path i_jump} {
[cb _history_menu]
}
"
label $w.header.commit \
tlabel $w.header.commit \
-textvariable @commit \
-background gold \
-foreground black \
-anchor w \
-justify left
label $w.header.path_l \
tlabel $w.header.path_l \
-text [mc "File:"] \
-background gold \
-foreground black \
-anchor w \
-justify left
set w_path $w.header.path
label $w_path \
tlabel $w_path \
-background gold \
-foreground black \
-anchor w \
@@ -209,10 +209,10 @@ constructor new {i_commit i_path i_jump} {
set w_columns [list $w_amov $w_asim $w_line $w_file]
scrollbar $w.file_pane.out.sbx \
${NS}::scrollbar $w.file_pane.out.sbx \
-orient h \
-command [list $w_file xview]
scrollbar $w.file_pane.out.sby \
${NS}::scrollbar $w.file_pane.out.sby \
-orient v \
-command [list scrollbar2many $w_columns yview]
eval grid $w_columns $w.file_pane.out.sby -sticky nsew
@@ -254,10 +254,10 @@ constructor new {i_commit i_path i_jump} {
-background $active_color \
-font font_ui
$w_cviewer tag raise sel
scrollbar $w.file_pane.cm.sbx \
${NS}::scrollbar $w.file_pane.cm.sbx \
-orient h \
-command [list $w_cviewer xview]
scrollbar $w.file_pane.cm.sby \
${NS}::scrollbar $w.file_pane.cm.sby \
-orient v \
-command [list $w_cviewer yview]
pack $w.file_pane.cm.sby -side right -fill y

View File

@@ -10,21 +10,24 @@ field opt_fetch 1; # refetch tracking branch if used?
field opt_detach 0; # force a detached head case?
constructor dialog {} {
make_toplevel top w
global use_ttk NS
make_dialog top w
wm withdraw $w
wm title $top [append "[appname] ([reponame]): " [mc "Checkout Branch"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
}
label $w.header -text [mc "Checkout Branch"] -font font_uibold
${NS}::label $w.header -text [mc "Checkout Branch"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x
frame $w.buttons
button $w.buttons.create -text [mc Checkout] \
${NS}::frame $w.buttons
${NS}::button $w.buttons.create -text [mc Checkout] \
-default active \
-command [cb _checkout]
pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc Cancel] \
${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
@@ -33,14 +36,14 @@ constructor dialog {} {
$w_rev bind_listbox <Double-Button-1> [cb _checkout]
pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5
labelframe $w.options -text [mc Options]
${NS}::labelframe $w.options -text [mc Options]
checkbutton $w.options.fetch \
${NS}::checkbutton $w.options.fetch \
-text [mc "Fetch Tracking Branch"] \
-variable @opt_fetch
pack $w.options.fetch -anchor nw
checkbutton $w.options.detach \
${NS}::checkbutton $w.options.detach \
-text [mc "Detach From Local Branch"] \
-variable @opt_detach
pack $w.options.detach -anchor nw
@@ -50,6 +53,7 @@ constructor dialog {} {
bind $w <Visibility> [cb _visible]
bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [cb _checkout]\;break
wm deiconify $w
tkwait window $w
}

View File

@@ -16,48 +16,48 @@ field opt_fetch 1; # refetch tracking branch if used?
field reset_ok 0; # did the user agree to reset?
constructor dialog {} {
global repo_config
global repo_config use_ttk NS
make_toplevel top w
make_dialog top w
wm withdraw $w
wm title $top [append "[appname] ([reponame]): " [mc "Create Branch"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
}
label $w.header -text [mc "Create New Branch"] -font font_uibold
${NS}::label $w.header -text [mc "Create New Branch"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x
frame $w.buttons
button $w.buttons.create -text [mc Create] \
${NS}::frame $w.buttons
${NS}::button $w.buttons.create -text [mc Create] \
-default active \
-command [cb _create]
pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc Cancel] \
${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.desc -text [mc "Branch Name"]
radiobutton $w.desc.name_r \
-anchor w \
${NS}::labelframe $w.desc -text [mc "Branch Name"]
${NS}::radiobutton $w.desc.name_r \
-text [mc "Name:"] \
-value user \
-variable @name_type
if {!$use_ttk} {$w.desc.name_r configure -anchor w}
set w_name $w.desc.name_t
entry $w_name \
-borderwidth 1 \
-relief sunken \
${NS}::entry $w_name \
-width 40 \
-textvariable @name \
-validate key \
-validatecommand [cb _validate %d %S]
grid $w.desc.name_r $w_name -sticky we -padx {0 5}
radiobutton $w.desc.match_r \
-anchor w \
${NS}::radiobutton $w.desc.match_r \
-text [mc "Match Tracking Branch Name"] \
-value match \
-variable @name_type
if {!$use_ttk} {$w.desc.match_r configure -anchor w}
grid $w.desc.match_r -sticky we -padx {0 5} -columnspan 2
grid columnconfigure $w.desc 1 -weight 1
@@ -66,34 +66,34 @@ constructor dialog {} {
set w_rev [::choose_rev::new $w.rev [mc "Starting Revision"]]
pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5
labelframe $w.options -text [mc Options]
${NS}::labelframe $w.options -text [mc Options]
frame $w.options.merge
label $w.options.merge.l -text [mc "Update Existing Branch:"]
${NS}::frame $w.options.merge
${NS}::label $w.options.merge.l -text [mc "Update Existing Branch:"]
pack $w.options.merge.l -side left
radiobutton $w.options.merge.no \
${NS}::radiobutton $w.options.merge.no \
-text [mc No] \
-value none \
-variable @opt_merge
pack $w.options.merge.no -side left
radiobutton $w.options.merge.ff \
${NS}::radiobutton $w.options.merge.ff \
-text [mc "Fast Forward Only"] \
-value ff \
-variable @opt_merge
pack $w.options.merge.ff -side left
radiobutton $w.options.merge.reset \
${NS}::radiobutton $w.options.merge.reset \
-text [mc Reset] \
-value reset \
-variable @opt_merge
pack $w.options.merge.reset -side left
pack $w.options.merge -anchor nw
checkbutton $w.options.fetch \
${NS}::checkbutton $w.options.fetch \
-text [mc "Fetch Tracking Branch"] \
-variable @opt_fetch
pack $w.options.fetch -anchor nw
checkbutton $w.options.checkout \
${NS}::checkbutton $w.options.checkout \
-text [mc "Checkout After Creation"] \
-variable @opt_checkout
pack $w.options.checkout -anchor nw
@@ -109,6 +109,7 @@ constructor dialog {} {
bind $w <Visibility> [cb _visible]
bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [cb _create]\;break
wm deiconify $w
tkwait window $w
}

View File

@@ -9,41 +9,40 @@ field w_check ; # revision picker for merge test
field w_delete ; # delete button
constructor dialog {} {
global current_branch
global current_branch use_ttk NS
make_toplevel top w
make_dialog top w
wm withdraw $w
wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
}
label $w.header -text [mc "Delete Local Branch"] -font font_uibold
${NS}::label $w.header -text [mc "Delete Local Branch"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x
frame $w.buttons
${NS}::frame $w.buttons
set w_delete $w.buttons.delete
button $w_delete \
${NS}::button $w_delete \
-text [mc Delete] \
-default active \
-state disabled \
-command [cb _delete]
pack $w_delete -side right
button $w.buttons.cancel \
${NS}::button $w.buttons.cancel \
-text [mc Cancel] \
-command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.list -text [mc "Local Branches"]
${NS}::labelframe $w.list -text [mc "Local Branches"]
set w_heads $w.list.l
listbox $w_heads \
slistbox $w_heads \
-height 10 \
-width 70 \
-selectmode extended \
-exportselection false \
-yscrollcommand [list $w.list.sby set]
scrollbar $w.list.sby -command [list $w.list.l yview]
pack $w.list.sby -side right -fill y
-exportselection false
pack $w.list.l -side left -fill both -expand 1
pack $w.list -fill both -expand 1 -pady 5 -padx 5
@@ -67,6 +66,7 @@ constructor dialog {} {
"
bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [cb _delete]\;break
wm deiconify $w
tkwait window $w
}

View File

@@ -8,9 +8,10 @@ field oldname
field newname
constructor dialog {} {
global current_branch
global current_branch use_ttk NS
make_toplevel top w
make_dialog top w
wm withdraw $w
wm title $top [append "[appname] ([reponame]): " [mc "Rename Branch"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
@@ -19,27 +20,31 @@ constructor dialog {} {
set oldname $current_branch
set newname [get_config gui.newbranchtemplate]
label $w.header -text [mc "Rename Branch"] -font font_uibold
${NS}::label $w.header -text [mc "Rename Branch"]\
-font font_uibold -anchor center
pack $w.header -side top -fill x
frame $w.buttons
button $w.buttons.rename -text [mc Rename] \
${NS}::frame $w.buttons
${NS}::button $w.buttons.rename -text [mc Rename] \
-default active \
-command [cb _rename]
pack $w.buttons.rename -side right
button $w.buttons.cancel -text [mc Cancel] \
${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
frame $w.rename
label $w.rename.oldname_l -text [mc "Branch:"]
eval tk_optionMenu $w.rename.oldname_m @oldname [load_all_heads]
${NS}::frame $w.rename
${NS}::label $w.rename.oldname_l -text [mc "Branch:"]
if {$use_ttk} {
ttk::combobox $w.rename.oldname_m -textvariable @oldname \
-values [load_all_heads] -state readonly
} else {
eval tk_optionMenu $w.rename.oldname_m @oldname [load_all_heads]
}
label $w.rename.newname_l -text [mc "New Name:"]
entry $w.rename.newname_t \
-borderwidth 1 \
-relief sunken \
${NS}::label $w.rename.newname_l -text [mc "New Name:"]
${NS}::entry $w.rename.newname_t \
-width 40 \
-textvariable @newname \
-validate key \
@@ -60,6 +65,7 @@ constructor dialog {} {
$w.rename.newname_t icursor end
focus $w.rename.newname_t
"
wm deiconify $w
tkwait window $w
}

View File

@@ -21,23 +21,23 @@ field browser_busy 1
field ls_buf {}; # Buffered record output from ls-tree
constructor new {commit {path {}}} {
global cursor_ptr M1B
make_toplevel top w
global cursor_ptr M1B use_ttk NS
make_dialog top w
wm withdraw $top
wm title $top [append "[appname] ([reponame]): " [mc "File Browser"]]
set browser_commit $commit
set browser_path $browser_commit:$path
label $w.path \
${NS}::label $w.path \
-textvariable @browser_path \
-anchor w \
-justify left \
-borderwidth 1 \
-relief sunken \
-font font_uibold
if {!$use_ttk} { $w.path configure -borderwidth 1 -relief sunken}
pack $w.path -anchor w -side top -fill x
frame $w.list
${NS}::frame $w.list
set w_list $w.list.l
text $w_list -background white -foreground black \
-borderwidth 0 \
@@ -49,19 +49,18 @@ constructor new {commit {path {}}} {
-xscrollcommand [list $w.list.sbx set] \
-yscrollcommand [list $w.list.sby set]
rmsel_tag $w_list
scrollbar $w.list.sbx -orient h -command [list $w_list xview]
scrollbar $w.list.sby -orient v -command [list $w_list yview]
${NS}::scrollbar $w.list.sbx -orient h -command [list $w_list xview]
${NS}::scrollbar $w.list.sby -orient v -command [list $w_list yview]
pack $w.list.sbx -side bottom -fill x
pack $w.list.sby -side right -fill y
pack $w_list -side left -fill both -expand 1
pack $w.list -side top -fill both -expand 1
label $w.status \
${NS}::label $w.status \
-textvariable @browser_status \
-anchor w \
-justify left \
-borderwidth 1 \
-relief sunken
-justify left
if {!$use_ttk} { $w.status configure -borderwidth 1 -relief sunken}
pack $w.status -anchor w -side bottom -fill x
bind $w_list <Button-1> "[cb _click 0 @%x,%y];break"
@@ -78,6 +77,7 @@ constructor new {commit {path {}}} {
bind $w_list <Right> break
bind $w_list <Visibility> [list focus $w_list]
wm deiconify $top
set w $w_list
if {$path ne {}} {
_ls $this $browser_commit:$path $path
@@ -263,23 +263,27 @@ field w ; # widget path
field w_rev ; # mega-widget to pick the initial revision
constructor dialog {} {
make_toplevel top w
global use_ttk NS
make_dialog top w
wm withdraw $top
wm title $top [append "[appname] ([reponame]): " [mc "Browse Branch Files"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
wm transient $top .
}
label $w.header \
${NS}::label $w.header \
-text [mc "Browse Branch Files"] \
-font font_uibold
-font font_uibold \
-anchor center
pack $w.header -side top -fill x
frame $w.buttons
button $w.buttons.browse -text [mc Browse] \
${NS}::frame $w.buttons
${NS}::button $w.buttons.browse -text [mc Browse] \
-default active \
-command [cb _open]
pack $w.buttons.browse -side right
button $w.buttons.cancel -text [mc Cancel] \
${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
@@ -291,6 +295,7 @@ constructor dialog {} {
bind $w <Visibility> [cb _visible]
bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [cb _open]\;break
wm deiconify $top
tkwait window $w
}

View File

@@ -17,6 +17,7 @@ variable all_families [list] ; # All fonts known to Tk
constructor pick {path title a_family a_size} {
variable all_families
global use_ttk NS
set v_family $a_family
set v_size $a_size
@@ -27,29 +28,30 @@ constructor pick {path title a_family a_size} {
set f_family $pv_family
set f_size $pv_size
make_toplevel top w
make_dialog top w
wm withdraw $top
wm title $top "[appname] ([reponame]): $title"
wm geometry $top "+[winfo rootx $path]+[winfo rooty $path]"
label $w.header -text $title -font font_uibold
${NS}::label $w.header -text $title -font font_uibold -anchor center
pack $w.header -side top -fill x
frame $w.buttons
button $w.buttons.select \
${NS}::frame $w.buttons
${NS}::button $w.buttons.select \
-text [mc Select] \
-default active \
-command [cb _select]
button $w.buttons.cancel \
${NS}::button $w.buttons.cancel \
-text [mc Cancel] \
-command [list destroy $w]
pack $w.buttons.select -side right
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
frame $w.inner
${NS}::frame $w.inner
frame $w.inner.family
label $w.inner.family.l \
${NS}::frame $w.inner.family
${NS}::label $w.inner.family.l \
-text [mc "Font Family"] \
-anchor w
set w_family $w.inner.family.v
@@ -64,16 +66,16 @@ constructor pick {path title a_family a_size} {
-height 10 \
-yscrollcommand [list $w.inner.family.sby set]
rmsel_tag $w_family
scrollbar $w.inner.family.sby -command [list $w_family yview]
${NS}::scrollbar $w.inner.family.sby -command [list $w_family yview]
pack $w.inner.family.l -side top -fill x
pack $w.inner.family.sby -side right -fill y
pack $w_family -fill both -expand 1
frame $w.inner.size
label $w.inner.size.l \
${NS}::frame $w.inner.size
${NS}::label $w.inner.size.l \
-text [mc "Font Size"] \
-anchor w
spinbox $w.inner.size.v \
tspinbox $w.inner.size.v \
-textvariable @f_size \
-from 2 -to 80 -increment 1 \
-width 3
@@ -86,8 +88,8 @@ constructor pick {path title a_family a_size} {
grid columnconfigure $w.inner 0 -weight 1
pack $w.inner -fill both -expand 1 -padx 5 -pady 5
frame $w.example
label $w.example.l \
${NS}::frame $w.example
${NS}::label $w.example.l \
-text [mc "Font Example"] \
-anchor w
set w_example $w.example.t
@@ -129,6 +131,7 @@ constructor pick {path title a_family a_size} {
grab $w
focus $w
"
wm deiconify $w
tkwait window $w
}

View File

@@ -22,9 +22,9 @@ field readtree_err ; # Error output from read-tree (if any)
field sorted_recent ; # recent repositories (sorted)
constructor pick {} {
global M1T M1B
global M1T M1B use_ttk NS
make_toplevel top w
make_dialog top w
wm title $top [mc "Git Gui"]
if {$top eq {.}} {
@@ -71,11 +71,11 @@ constructor pick {} {
set w_body $w.body
set opts $w_body.options
frame $w_body
${NS}::frame $w_body
text $opts \
-cursor $::cursor_ptr \
-relief flat \
-background [$w_body cget -background] \
-background [get_bg_color $w_body] \
-wrap none \
-spacing1 5 \
-width 50 \
@@ -132,15 +132,15 @@ constructor pick {} {
-label [mc "Recent Repositories"]
}
label $w_body.space
label $w_body.recentlabel \
${NS}::label $w_body.space
${NS}::label $w_body.recentlabel \
-anchor w \
-text [mc "Open Recent Repository:"]
set w_recentlist $w_body.recentlist
text $w_recentlist \
-cursor $::cursor_ptr \
-relief flat \
-background [$w_body.recentlabel cget -background] \
-background [get_bg_color $w_body.recentlabel] \
-wrap none \
-width 50 \
-height 10
@@ -176,10 +176,10 @@ constructor pick {} {
}
pack $w_body -fill x -padx 10 -pady 10
frame $w.buttons
${NS}::frame $w.buttons
set w_next $w.buttons.next
set w_quit $w.buttons.quit
button $w_quit \
${NS}::button $w_quit \
-text [mc "Quit"] \
-command exit
pack $w_quit -side right -padx 5
@@ -203,6 +203,7 @@ constructor pick {} {
wm deiconify $top
tkwait variable @done
grab release $top
if {$top eq {.}} {
eval destroy [winfo children $top]
}
@@ -284,9 +285,10 @@ method _open_recent_path {p} {
}
method _next {action} {
global NS
destroy $w_body
if {![winfo exists $w_next]} {
button $w_next -default active
${NS}::button $w_next -default active
pack $w_next -side right -padx 5 -before $w_quit
}
_do_$action $this
@@ -375,26 +377,25 @@ proc _objdir {path} {
## Create New Repository
method _do_new {} {
global use_ttk NS
$w_next conf \
-state disabled \
-command [cb _do_new2] \
-text [mc "Create"]
frame $w_body
label $w_body.h \
-font font_uibold \
${NS}::frame $w_body
${NS}::label $w_body.h \
-font font_uibold -anchor center \
-text [mc "Create New Repository"]
pack $w_body.h -side top -fill x -pady 10
pack $w_body -fill x -padx 10
frame $w_body.where
label $w_body.where.l -text [mc "Directory:"]
entry $w_body.where.t \
${NS}::frame $w_body.where
${NS}::label $w_body.where.l -text [mc "Directory:"]
${NS}::entry $w_body.where.t \
-textvariable @local_path \
-borderwidth 1 \
-relief sunken \
-width 50
button $w_body.where.b \
${NS}::button $w_body.where.b \
-text [mc "Browse"] \
-command [cb _new_local_path]
set w_localpath $w_body.where.t
@@ -460,63 +461,57 @@ proc _new_ok {p} {
## Clone Existing Repository
method _do_clone {} {
global use_ttk NS
$w_next conf \
-state disabled \
-command [cb _do_clone2] \
-text [mc "Clone"]
frame $w_body
label $w_body.h \
-font font_uibold \
${NS}::frame $w_body
${NS}::label $w_body.h \
-font font_uibold -anchor center \
-text [mc "Clone Existing Repository"]
pack $w_body.h -side top -fill x -pady 10
pack $w_body -fill x -padx 10
set args $w_body.args
frame $w_body.args
${NS}::frame $w_body.args
pack $args -fill both
label $args.origin_l -text [mc "Source Location:"]
entry $args.origin_t \
${NS}::label $args.origin_l -text [mc "Source Location:"]
${NS}::entry $args.origin_t \
-textvariable @origin_url \
-borderwidth 1 \
-relief sunken \
-width 50
button $args.origin_b \
${NS}::button $args.origin_b \
-text [mc "Browse"] \
-command [cb _open_origin]
grid $args.origin_l $args.origin_t $args.origin_b -sticky ew
label $args.where_l -text [mc "Target Directory:"]
entry $args.where_t \
${NS}::label $args.where_l -text [mc "Target Directory:"]
${NS}::entry $args.where_t \
-textvariable @local_path \
-borderwidth 1 \
-relief sunken \
-width 50
button $args.where_b \
${NS}::button $args.where_b \
-text [mc "Browse"] \
-command [cb _new_local_path]
grid $args.where_l $args.where_t $args.where_b -sticky ew
set w_localpath $args.where_t
label $args.type_l -text [mc "Clone Type:"]
frame $args.type_f
${NS}::label $args.type_l -text [mc "Clone Type:"]
${NS}::frame $args.type_f
set w_types [list]
lappend w_types [radiobutton $args.type_f.hardlink \
lappend w_types [${NS}::radiobutton $args.type_f.hardlink \
-state disabled \
-anchor w \
-text [mc "Standard (Fast, Semi-Redundant, Hardlinks)"] \
-variable @clone_type \
-value hardlink]
lappend w_types [radiobutton $args.type_f.full \
lappend w_types [${NS}::radiobutton $args.type_f.full \
-state disabled \
-anchor w \
-text [mc "Full Copy (Slower, Redundant Backup)"] \
-variable @clone_type \
-value full]
lappend w_types [radiobutton $args.type_f.shared \
lappend w_types [${NS}::radiobutton $args.type_f.shared \
-state disabled \
-anchor w \
-text [mc "Shared (Fastest, Not Recommended, No Backup)"] \
-variable @clone_type \
-value shared]
@@ -1005,26 +1000,25 @@ method _postcheckout_wait {fd_ph} {
## Open Existing Repository
method _do_open {} {
global NS
$w_next conf \
-state disabled \
-command [cb _do_open2] \
-text [mc "Open"]
frame $w_body
label $w_body.h \
-font font_uibold \
${NS}::frame $w_body
${NS}::label $w_body.h \
-font font_uibold -anchor center \
-text [mc "Open Existing Repository"]
pack $w_body.h -side top -fill x -pady 10
pack $w_body -fill x -padx 10
frame $w_body.where
label $w_body.where.l -text [mc "Repository:"]
entry $w_body.where.t \
${NS}::frame $w_body.where
${NS}::label $w_body.where.l -text [mc "Repository:"]
${NS}::entry $w_body.where.t \
-textvariable @local_path \
-borderwidth 1 \
-relief sunken \
-width 50
button $w_body.where.b \
${NS}::button $w_body.where.b \
-text [mc "Browse"] \
-command [cb _open_local_path]

View File

@@ -10,7 +10,7 @@ field w_list ; # list of currently filtered specs
field w_filter ; # filter entry for $w_list
field c_expr {}; # current revision expression
field filter ; # current filter string
field filter ""; # current filter string
field revtype head; # type of revision chosen
field cur_specs [list]; # list of specs for $revtype
field spec_head ; # list of all head specs
@@ -32,7 +32,7 @@ proc new_unmerged {path {title {}}} {
}
constructor _new {path unmerged_only title} {
global current_branch is_detached
global current_branch is_detached use_ttk NS
if {![info exists ::all_remotes]} {
load_all_remotes
@@ -41,65 +41,65 @@ constructor _new {path unmerged_only title} {
set w $path
if {$title ne {}} {
labelframe $w -text $title
${NS}::labelframe $w -text $title
} else {
frame $w
${NS}::frame $w
}
bind $w <Destroy> [cb _delete %W]
if {$is_detached} {
radiobutton $w.detachedhead_r \
-anchor w \
${NS}::radiobutton $w.detachedhead_r \
-text [mc "This Detached Checkout"] \
-value HEAD \
-variable @revtype
if {!$use_ttk} {$w.detachedhead_r configure -anchor w}
grid $w.detachedhead_r -sticky we -padx {0 5} -columnspan 2
}
radiobutton $w.expr_r \
${NS}::radiobutton $w.expr_r \
-text [mc "Revision Expression:"] \
-value expr \
-variable @revtype
entry $w.expr_t \
-borderwidth 1 \
-relief sunken \
${NS}::entry $w.expr_t \
-width 50 \
-textvariable @c_expr \
-validate key \
-validatecommand [cb _validate %d %S]
grid $w.expr_r $w.expr_t -sticky we -padx {0 5}
frame $w.types
radiobutton $w.types.head_r \
${NS}::frame $w.types
${NS}::radiobutton $w.types.head_r \
-text [mc "Local Branch"] \
-value head \
-variable @revtype
pack $w.types.head_r -side left
radiobutton $w.types.trck_r \
${NS}::radiobutton $w.types.trck_r \
-text [mc "Tracking Branch"] \
-value trck \
-variable @revtype
pack $w.types.trck_r -side left
radiobutton $w.types.tag_r \
${NS}::radiobutton $w.types.tag_r \
-text [mc "Tag"] \
-value tag \
-variable @revtype
pack $w.types.tag_r -side left
set w_filter $w.types.filter
entry $w_filter \
-borderwidth 1 \
-relief sunken \
${NS}::entry $w_filter \
-width 12 \
-textvariable @filter \
-validate key \
-validatecommand [cb _filter %P]
pack $w_filter -side right
pack [label $w.types.filter_icon \
pack [${NS}::label $w.types.filter_icon \
-image ::choose_rev::img_find \
] -side right
grid $w.types -sticky we -padx {0 5} -columnspan 2
frame $w.list
if {$use_ttk} {
ttk::frame $w.list -style SListbox.TFrame -padding 2
} else {
frame $w.list
}
set w_list $w.list.l
listbox $w_list \
-font font_diff \
@@ -109,6 +109,9 @@ constructor _new {path unmerged_only title} {
-exportselection false \
-xscrollcommand [cb _sb_set $w.list.sbx h] \
-yscrollcommand [cb _sb_set $w.list.sby v]
if {$use_ttk} {
$w_list configure -relief flat -highlightthickness 0 -borderwidth 0
}
pack $w_list -fill both -expand 1
grid $w.list -sticky nswe -padx {20 5} -columnspan 2
bind $w_list <Any-Motion> [cb _show_tooltip @%x,%y]
@@ -235,11 +238,12 @@ constructor _new {path unmerged_only title} {
}
method none {text} {
global NS use_ttk
if {![winfo exists $w.none_r]} {
radiobutton $w.none_r \
-anchor w \
${NS}::radiobutton $w.none_r \
-value none \
-variable @revtype
if {!$use_ttk} {$w.none_r configure -anchor w}
grid $w.none_r -sticky we -padx {0 5} -columnspan 2
}
$w.none_r configure -text $text
@@ -425,6 +429,7 @@ method _delete {current} {
}
method _sb_set {sb orient first last} {
global NS
set old_focus [focus -lastfor $w]
if {$first == 0 && $last == 1} {
@@ -440,10 +445,10 @@ method _sb_set {sb orient first last} {
if {![winfo exists $sb]} {
if {$orient eq {h}} {
scrollbar $sb -orient h -command [list $w_list xview]
${NS}::scrollbar $sb -orient h -command [list $w_list xview]
pack $sb -fill x -side bottom -before $w_list
} else {
scrollbar $sb -orient v -command [list $w_list yview]
${NS}::scrollbar $sb -orient v -command [list $w_list yview]
pack $sb -fill y -side right -before $w_list
}
if {$old_focus ne {}} {

View File

@@ -134,6 +134,13 @@ proc delete_this {{t {}}} {
if {[namespace exists $t]} {namespace delete $t}
}
proc make_dialog {t w args} {
upvar $t top $w pfx this this
global use_ttk
uplevel [linsert $args 0 make_toplevel $t $w]
pave_toplevel $pfx
}
proc make_toplevel {t w args} {
upvar $t top $w pfx this this

View File

@@ -27,20 +27,20 @@ constructor embed {path title} {
}
method _init {} {
global M1B
global M1B use_ttk NS
if {$is_toplevel} {
make_toplevel top w -autodelete 0
make_dialog top w -autodelete 0
wm title $top "[appname] ([reponame]): $t_short"
} else {
frame $w
${NS}::frame $w
}
set console_cr 1.0
set w_t $w.m.t
frame $w.m
label $w.m.l1 \
${NS}::frame $w.m
${NS}::label $w.m.l1 \
-textvariable @t_long \
-anchor w \
-justify left \
@@ -78,7 +78,7 @@ method _init {} {
"
if {$is_toplevel} {
button $w.ok -text [mc "Close"] \
${NS}::button $w.ok -text [mc "Close"] \
-state disabled \
-command [list destroy $w]
pack $w.ok -side bottom -anchor e -pady 10 -padx 10
@@ -206,13 +206,14 @@ method done {ok} {
}
method _sb_set {sb orient first last} {
global NS
if {![winfo exists $sb]} {
if {$first == $last || ($first == 0 && $last == 1)} return
if {$orient eq {h}} {
scrollbar $sb -orient h -command [list $w_t xview]
${NS}::scrollbar $sb -orient h -command [list $w_t xview]
pack $sb -fill x -side bottom -before $w_t
} else {
scrollbar $sb -orient v -command [list $w_t yview]
${NS}::scrollbar $sb -orient v -command [list $w_t yview]
pack $sb -fill y -side right -before $w_t
}
}

View File

@@ -2,6 +2,7 @@
# Copyright (C) 2006, 2007 Shawn Pearce
proc do_stats {} {
global use_ttk NS
set fd [git_read count-objects -v]
while {[gets $fd line] > 0} {
if {[regexp {^([^:]+): (\d+)$} $line _ name value]} {
@@ -21,24 +22,22 @@ proc do_stats {} {
}
set w .stats_view
toplevel $w
Dialog $w
wm withdraw $w
wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
label $w.header -text [mc "Database Statistics"]
pack $w.header -side top -fill x
frame $w.buttons -border 1
button $w.buttons.close -text [mc Close] \
${NS}::frame $w.buttons
${NS}::button $w.buttons.close -text [mc Close] \
-default active \
-command [list destroy $w]
button $w.buttons.gc -text [mc "Compress Database"] \
${NS}::button $w.buttons.gc -text [mc "Compress Database"] \
-default normal \
-command "destroy $w;do_gc"
pack $w.buttons.close -side right
pack $w.buttons.gc -side left
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
frame $w.stat -borderwidth 1 -relief solid
${NS}::labelframe $w.stat -text [mc "Database Statistics"]
foreach s {
{count {mc "Number of loose objects"}}
{size {mc "Disk space used by loose objects"} { KiB}}
@@ -55,8 +54,8 @@ proc do_stats {} {
set value "$value[lindex $s 2]"
}
label $w.stat.l_$name -text "$label:" -anchor w
label $w.stat.v_$name -text $value -anchor w
${NS}::label $w.stat.l_$name -text "$label:" -anchor w
${NS}::label $w.stat.v_$name -text $value -anchor w
grid $w.stat.l_$name $w.stat.v_$name -sticky we -padx {0 5}
}
pack $w.stat -pady 10 -padx 10
@@ -65,6 +64,7 @@ proc do_stats {} {
bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [list destroy $w]
wm title $w [append "[appname] ([reponame]): " [mc "Database Statistics"]]
wm deiconify $w
tkwait window $w
}

View File

@@ -281,6 +281,15 @@ proc start_show_diff {cont_info {add_opts {}}} {
}
}
if {[string match {160000 *} [lindex $s 2]]
|| [string match {160000 *} [lindex $s 3]]} {
set is_submodule_diff 1
if {[git-version >= "1.6.6"]} {
lappend cmd --submodule
}
}
lappend cmd -p
lappend cmd --no-color
if {$repo_config(gui.diffcontext) >= 1} {
@@ -296,9 +305,7 @@ proc start_show_diff {cont_info {add_opts {}}} {
lappend cmd $path
}
if {[string match {160000 *} [lindex $s 2]]
|| [string match {160000 *} [lindex $s 3]]} {
set is_submodule_diff 1
if {$is_submodule_diff && [git-version < "1.6.6"]} {
if {$w eq $ui_index} {
set cmd [list submodule summary --cached -- $path]
} else {
@@ -387,7 +394,9 @@ proc read_diff {fd cont_info} {
}
} elseif {$is_submodule_diff} {
if {$line == ""} continue
if {[regexp {^\* } $line]} {
if {[regexp {^Submodule } $line]} {
set tags d_@
} elseif {[regexp {^\* } $line]} {
set line [string replace $line 0 1 {Submodule }]
set tags d_@
} else {
@@ -533,10 +542,23 @@ proc apply_hunk {x y} {
}
}
proc apply_line {x y} {
proc apply_range_or_line {x y} {
global current_diff_path current_diff_header current_diff_side
global ui_diff ui_index file_states
set selected [$ui_diff tag nextrange sel 0.0]
if {$selected == {}} {
set first [$ui_diff index "@$x,$y"]
set last $first
} else {
set first [lindex $selected 0]
set last [lindex $selected 1]
}
set first_l [$ui_diff index "$first linestart"]
set last_l [$ui_diff index "$last lineend"]
if {$current_diff_path eq {} || $current_diff_header eq {}} return
if {![lock_index apply_hunk]} return
@@ -559,120 +581,147 @@ proc apply_line {x y} {
}
}
set the_l [$ui_diff index @$x,$y]
set wholepatch {}
# operate only on change lines
set c1 [$ui_diff get "$the_l linestart"]
if {$c1 ne {+} && $c1 ne {-}} {
unlock_index
return
}
set sign $c1
set i_l [$ui_diff search -backwards -regexp ^@@ $the_l 0.0]
if {$i_l eq {}} {
unlock_index
return
}
# $i_l is now at the beginning of a line
# pick start line number from hunk header
set hh [$ui_diff get $i_l "$i_l + 1 lines"]
set hh [lindex [split $hh ,] 0]
set hln [lindex [split $hh -] 1]
# There is a special situation to take care of. Consider this hunk:
#
# @@ -10,4 +10,4 @@
# context before
# -old 1
# -old 2
# +new 1
# +new 2
# context after
#
# We used to keep the context lines in the order they appear in the
# hunk. But then it is not possible to correctly stage only
# "-old 1" and "+new 1" - it would result in this staged text:
#
# context before
# old 2
# new 1
# context after
#
# (By symmetry it is not possible to *un*stage "old 2" and "new 2".)
#
# We resolve the problem by introducing an asymmetry, namely, when
# a "+" line is *staged*, it is moved in front of the context lines
# that are generated from the "-" lines that are immediately before
# the "+" block. That is, we construct this patch:
#
# @@ -10,4 +10,5 @@
# context before
# +new 1
# old 1
# old 2
# context after
#
# But we do *not* treat "-" lines that are *un*staged in a special
# way.
#
# With this asymmetry it is possible to stage the change
# "old 1" -> "new 1" directly, and to stage the change
# "old 2" -> "new 2" by first staging the entire hunk and
# then unstaging the change "old 1" -> "new 1".
# This is non-empty if and only if we are _staging_ changes;
# then it accumulates the consecutive "-" lines (after converting
# them to context lines) in order to be moved after the "+" change
# line.
set pre_context {}
set n 0
set i_l [$ui_diff index "$i_l + 1 lines"]
set patch {}
while {[$ui_diff compare $i_l < "end - 1 chars"] &&
[$ui_diff get $i_l "$i_l + 2 chars"] ne {@@}} {
set next_l [$ui_diff index "$i_l + 1 lines"]
set c1 [$ui_diff get $i_l]
if {[$ui_diff compare $i_l <= $the_l] &&
[$ui_diff compare $the_l < $next_l]} {
# the line to stage/unstage
set ln [$ui_diff get $i_l $next_l]
if {$c1 eq {-}} {
set n [expr $n+1]
set patch "$patch$pre_context$ln"
} else {
set patch "$patch$ln$pre_context"
}
set pre_context {}
} elseif {$c1 ne {-} && $c1 ne {+}} {
# context line
set ln [$ui_diff get $i_l $next_l]
set patch "$patch$pre_context$ln"
set n [expr $n+1]
set pre_context {}
} elseif {$c1 eq $to_context} {
# turn change line into context line
set ln [$ui_diff get "$i_l + 1 chars" $next_l]
if {$c1 eq {-}} {
set pre_context "$pre_context $ln"
} else {
set patch "$patch $ln"
}
set n [expr $n+1]
while {$first_l < $last_l} {
set i_l [$ui_diff search -backwards -regexp ^@@ $first_l 0.0]
if {$i_l eq {}} {
# If there's not a @@ above, then the selected range
# must have come before the first_l @@
set i_l [$ui_diff search -regexp ^@@ $first_l $last_l]
}
set i_l $next_l
if {$i_l eq {}} {
unlock_index
return
}
# $i_l is now at the beginning of a line
# pick start line number from hunk header
set hh [$ui_diff get $i_l "$i_l + 1 lines"]
set hh [lindex [split $hh ,] 0]
set hln [lindex [split $hh -] 1]
# There is a special situation to take care of. Consider this
# hunk:
#
# @@ -10,4 +10,4 @@
# context before
# -old 1
# -old 2
# +new 1
# +new 2
# context after
#
# We used to keep the context lines in the order they appear in
# the hunk. But then it is not possible to correctly stage only
# "-old 1" and "+new 1" - it would result in this staged text:
#
# context before
# old 2
# new 1
# context after
#
# (By symmetry it is not possible to *un*stage "old 2" and "new
# 2".)
#
# We resolve the problem by introducing an asymmetry, namely,
# when a "+" line is *staged*, it is moved in front of the
# context lines that are generated from the "-" lines that are
# immediately before the "+" block. That is, we construct this
# patch:
#
# @@ -10,4 +10,5 @@
# context before
# +new 1
# old 1
# old 2
# context after
#
# But we do *not* treat "-" lines that are *un*staged in a
# special way.
#
# With this asymmetry it is possible to stage the change "old
# 1" -> "new 1" directly, and to stage the change "old 2" ->
# "new 2" by first staging the entire hunk and then unstaging
# the change "old 1" -> "new 1".
#
# Applying multiple lines adds complexity to the special
# situation. The pre_context must be moved after the entire
# first block of consecutive staged "+" lines, so that
# staging both additions gives the following patch:
#
# @@ -10,4 +10,6 @@
# context before
# +new 1
# +new 2
# old 1
# old 2
# context after
# This is non-empty if and only if we are _staging_ changes;
# then it accumulates the consecutive "-" lines (after
# converting them to context lines) in order to be moved after
# "+" change lines.
set pre_context {}
set n 0
set m 0
set i_l [$ui_diff index "$i_l + 1 lines"]
set patch {}
while {[$ui_diff compare $i_l < "end - 1 chars"] &&
[$ui_diff get $i_l "$i_l + 2 chars"] ne {@@}} {
set next_l [$ui_diff index "$i_l + 1 lines"]
set c1 [$ui_diff get $i_l]
if {[$ui_diff compare $first_l <= $i_l] &&
[$ui_diff compare $i_l < $last_l] &&
($c1 eq {-} || $c1 eq {+})} {
# a line to stage/unstage
set ln [$ui_diff get $i_l $next_l]
if {$c1 eq {-}} {
set n [expr $n+1]
set patch "$patch$pre_context$ln"
set pre_context {}
} else {
set m [expr $m+1]
set patch "$patch$ln"
}
} elseif {$c1 ne {-} && $c1 ne {+}} {
# context line
set ln [$ui_diff get $i_l $next_l]
set patch "$patch$pre_context$ln"
set n [expr $n+1]
set m [expr $m+1]
set pre_context {}
} elseif {$c1 eq $to_context} {
# turn change line into context line
set ln [$ui_diff get "$i_l + 1 chars" $next_l]
if {$c1 eq {-}} {
set pre_context "$pre_context $ln"
} else {
set patch "$patch $ln"
}
set n [expr $n+1]
set m [expr $m+1]
} else {
# a change in the opposite direction of
# to_context which is outside the range of
# lines to apply.
set patch "$patch$pre_context"
set pre_context {}
}
set i_l $next_l
}
set patch "$patch$pre_context"
set wholepatch "$wholepatch@@ -$hln,$n +$hln,$m @@\n$patch"
set first_l [$ui_diff index "$next_l + 1 lines"]
}
set patch "$patch$pre_context"
set patch "@@ -$hln,$n +$hln,[eval expr $n $sign 1] @@\n$patch"
if {[catch {
set enc [get_path_encoding $current_diff_path]
set p [eval git_write $apply_cmd]
fconfigure $p -translation binary -encoding $enc
puts -nonewline $p $current_diff_header
puts -nonewline $p $patch
puts -nonewline $p $wholepatch
close $p} err]} {
error_popup [append $failed_msg "\n\n$err"]
}

View File

@@ -71,11 +71,13 @@ proc ask_popup {msg} {
}
proc hook_failed_popup {hook msg {is_fatal 1}} {
global use_ttk NS
set w .hookfail
toplevel $w
Dialog $w
wm withdraw $w
frame $w.m
label $w.m.l1 -text "$hook hook failed:" \
${NS}::frame $w.m
${NS}::label $w.m.l1 -text "$hook hook failed:" \
-anchor w \
-justify left \
-font font_uibold
@@ -87,10 +89,10 @@ proc hook_failed_popup {hook msg {is_fatal 1}} {
-width 80 -height 10 \
-font font_diff \
-yscrollcommand [list $w.m.sby set]
scrollbar $w.m.sby -command [list $w.m.t yview]
${NS}::scrollbar $w.m.sby -command [list $w.m.t yview]
pack $w.m.l1 -side top -fill x
if {$is_fatal} {
label $w.m.l2 \
${NS}::label $w.m.l2 \
-text [mc "You must correct the above errors before committing."] \
-anchor w \
-justify left \
@@ -104,7 +106,7 @@ proc hook_failed_popup {hook msg {is_fatal 1}} {
$w.m.t insert 1.0 $msg
$w.m.t conf -state disabled
button $w.ok -text OK \
${NS}::button $w.ok -text OK \
-width 15 \
-command "destroy $w"
pack $w.ok -side bottom -anchor e -pady 10 -padx 10
@@ -112,5 +114,6 @@ proc hook_failed_popup {hook msg {is_fatal 1}} {
bind $w <Visibility> "grab $w; focus $w"
bind $w <Key-Return> "destroy $w"
wm title $w [strcat "[appname] ([reponame]): " [mc "error"]]
wm deiconify $w
tkwait window $w
}

View File

@@ -8,26 +8,28 @@ proc _delete_indexlock {} {
}
proc _close_updateindex {fd after} {
global use_ttk NS
fconfigure $fd -blocking 1
if {[catch {close $fd} err]} {
set w .indexfried
toplevel $w
Dialog $w
wm withdraw $w
wm title $w [strcat "[appname] ([reponame]): " [mc "Index Error"]]
wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
set s [mc "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui."]
text $w.msg -yscrollcommand [list $w.vs set] \
-width [string length $s] -relief flat \
-borderwidth 0 -highlightthickness 0 \
-background [$w cget -background]
-background [get_bg_color $w]
$w.msg tag configure bold -font font_uibold -justify center
scrollbar $w.vs -command [list $w.msg yview]
${NS}::scrollbar $w.vs -command [list $w.msg yview]
$w.msg insert end $s bold \n\n$err {}
$w.msg configure -state disabled
button $w.continue \
${NS}::button $w.continue \
-text [mc "Continue"] \
-command [list destroy $w]
button $w.unlock \
${NS}::button $w.unlock \
-text [mc "Unlock Index"] \
-command "destroy $w; _delete_indexlock"
grid $w.msg - $w.vs -sticky news
@@ -40,6 +42,7 @@ proc _close_updateindex {fd after} {
grab $w
focus %W
"
wm deiconify $w
tkwait window $w
$::main_status stop

View File

@@ -139,14 +139,14 @@ method _finish {cons ok} {
constructor dialog {} {
global current_branch
global M1B
global M1B use_ttk NS
if {![_can_merge $this]} {
delete_this
return
}
make_toplevel top w
make_dialog top w
wm title $top [append "[appname] ([reponame]): " [mc "Merge"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
@@ -154,21 +154,21 @@ constructor dialog {} {
set _start [cb _start]
label $w.header \
${NS}::label $w.header \
-text [mc "Merge Into %s" $current_branch] \
-font font_uibold
pack $w.header -side top -fill x
frame $w.buttons
button $w.buttons.visualize \
${NS}::frame $w.buttons
${NS}::button $w.buttons.visualize \
-text [mc Visualize] \
-command [cb _visualize]
pack $w.buttons.visualize -side left
button $w.buttons.merge \
${NS}::button $w.buttons.merge \
-text [mc Merge] \
-command $_start
pack $w.buttons.merge -side right
button $w.buttons.cancel \
${NS}::button $w.buttons.cancel \
-text [mc "Cancel"] \
-command [cb _cancel]
pack $w.buttons.cancel -side right -padx 5

View File

@@ -91,7 +91,7 @@ proc save_config {} {
proc do_options {} {
global repo_config global_config font_descs
global repo_config_new global_config_new
global ui_comm_spell
global ui_comm_spell use_ttk NS
array unset repo_config_new
array unset global_config_new
@@ -110,26 +110,28 @@ proc do_options {} {
}
set w .options_editor
toplevel $w
Dialog $w
wm withdraw $w
wm transient $w [winfo parent $w]
wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
frame $w.buttons
button $w.buttons.restore -text [mc "Restore Defaults"] \
${NS}::frame $w.buttons
${NS}::button $w.buttons.restore -text [mc "Restore Defaults"] \
-default normal \
-command do_restore_defaults
pack $w.buttons.restore -side left
button $w.buttons.save -text [mc Save] \
${NS}::button $w.buttons.save -text [mc Save] \
-default active \
-command [list do_save_config $w]
pack $w.buttons.save -side right
button $w.buttons.cancel -text [mc "Cancel"] \
${NS}::button $w.buttons.cancel -text [mc "Cancel"] \
-default normal \
-command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.repo -text [mc "%s Repository" [reponame]]
labelframe $w.global -text [mc "Global (All Repositories)"]
${NS}::labelframe $w.repo -text [mc "%s Repository" [reponame]]
${NS}::labelframe $w.global -text [mc "Global (All Repositories)"]
pack $w.repo -side left -fill both -expand 1 -pady 5 -padx 5
pack $w.global -side right -fill both -expand 1 -pady 5 -padx 5
@@ -161,7 +163,7 @@ proc do_options {} {
foreach f {repo global} {
switch -glob -- $type {
b {
checkbutton $w.$f.$optid -text $text \
${NS}::checkbutton $w.$f.$optid -text $text \
-variable ${f}_config_new($name) \
-onvalue true \
-offvalue false
@@ -169,10 +171,10 @@ proc do_options {} {
}
i-* {
regexp -- {-(\d+)\.\.(\d+)$} $type _junk min max
frame $w.$f.$optid
label $w.$f.$optid.l -text "$text:"
${NS}::frame $w.$f.$optid
${NS}::label $w.$f.$optid.l -text "$text:"
pack $w.$f.$optid.l -side left -anchor w -fill x
spinbox $w.$f.$optid.v \
tspinbox $w.$f.$optid.v \
-textvariable ${f}_config_new($name) \
-from $min \
-to $max \
@@ -184,11 +186,9 @@ proc do_options {} {
}
c -
t {
frame $w.$f.$optid
label $w.$f.$optid.l -text "$text:"
entry $w.$f.$optid.v \
-borderwidth 1 \
-relief sunken \
${NS}::frame $w.$f.$optid
${NS}::label $w.$f.$optid.l -text "$text:"
${NS}::entry $w.$f.$optid.v \
-width 20 \
-textvariable ${f}_config_new($name)
pack $w.$f.$optid.l -side left -anchor w
@@ -199,7 +199,7 @@ proc do_options {} {
menu $w.$f.$optid.m
build_encoding_menu $w.$f.$optid.m \
[list set ${f}_config_new($name)] 1
button $w.$f.$optid.b \
${NS}::button $w.$f.$optid.b \
-text [mc "Change"] \
-command [list popup_btn_menu \
$w.$f.$optid.m $w.$f.$optid.b]
@@ -226,11 +226,17 @@ proc do_options {} {
set ${f}_config_new(gui.spellingdictionary) $value
}
frame $w.$f.$optid
label $w.$f.$optid.l -text [mc "Spelling Dictionary:"]
eval tk_optionMenu $w.$f.$optid.v \
${f}_config_new(gui.spellingdictionary) \
$all_dicts
${NS}::frame $w.$f.$optid
${NS}::label $w.$f.$optid.l -text [mc "Spelling Dictionary:"]
if {$use_ttk} {
ttk::combobox $w.$f.$optid.v \
-textvariable ${f}_config_new(gui.spellingdictionary) \
-values $all_dicts -state readonly
} else {
eval tk_optionMenu $w.$f.$optid.v \
${f}_config_new(gui.spellingdictionary) \
$all_dicts
}
pack $w.$f.$optid.l -side left -anchor w -fill x
pack $w.$f.$optid.v -side right -anchor e -padx 5
pack $w.$f.$optid -side top -anchor w -fill x
@@ -248,20 +254,20 @@ proc do_options {} {
set global_config_new(gui.$font^^size) \
[font configure $font -size]
frame $w.global.$name
label $w.global.$name.l -text "$text:"
button $w.global.$name.b \
${NS}::frame $w.global.$name
${NS}::label $w.global.$name.l -text "$text:"
${NS}::button $w.global.$name.b \
-text [mc "Change Font"] \
-command [list \
choose_font::pick \
tchoosefont \
$w \
[mc "Choose %s" $text] \
global_config_new(gui.$font^^family) \
global_config_new(gui.$font^^size) \
]
label $w.global.$name.f -textvariable global_config_new(gui.$font^^family)
label $w.global.$name.s -textvariable global_config_new(gui.$font^^size)
label $w.global.$name.pt -text [mc "pt."]
${NS}::label $w.global.$name.f -textvariable global_config_new(gui.$font^^family)
${NS}::label $w.global.$name.s -textvariable global_config_new(gui.$font^^size)
${NS}::label $w.global.$name.pt -text [mc "pt."]
pack $w.global.$name.l -side left -anchor w
pack $w.global.$name.b -side right -anchor e
pack $w.global.$name.pt -side right -anchor w
@@ -280,6 +286,7 @@ proc do_options {} {
set t [mc "Options"]
}
wm title $w "[appname] ([reponame]): $t"
wm deiconify $w
tkwait window $w
}

View File

@@ -13,45 +13,43 @@ field location {}; # location of the remote the user has chosen
field opt_action fetch; # action to do after registering the remote locally
constructor dialog {} {
global repo_config
global repo_config use_ttk NS
make_toplevel top w
make_dialog top w
wm withdraw $top
wm title $top [append "[appname] ([reponame]): " [mc "Add Remote"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
}
label $w.header -text [mc "Add New Remote"] -font font_uibold
${NS}::label $w.header -text [mc "Add New Remote"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x
frame $w.buttons
button $w.buttons.create -text [mc Add] \
${NS}::frame $w.buttons
${NS}::button $w.buttons.create -text [mc Add] \
-default active \
-command [cb _add]
pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc Cancel] \
${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.desc -text [mc "Remote Details"]
${NS}::labelframe $w.desc -text [mc "Remote Details"]
label $w.desc.name_l -text [mc "Name:"]
${NS}::label $w.desc.name_l -text [mc "Name:"]
set w_name $w.desc.name_t
entry $w_name \
-borderwidth 1 \
-relief sunken \
${NS}::entry $w_name \
-width 40 \
-textvariable @name \
-validate key \
-validatecommand [cb _validate_name %d %S]
grid $w.desc.name_l $w_name -sticky we -padx {0 5}
label $w.desc.loc_l -text [mc "Location:"]
${NS}::label $w.desc.loc_l -text [mc "Location:"]
set w_loc $w.desc.loc_t
entry $w_loc \
-borderwidth 1 \
-relief sunken \
${NS}::entry $w_loc \
-width 40 \
-textvariable @location
grid $w.desc.loc_l $w_loc -sticky we -padx {0 5}
@@ -59,21 +57,21 @@ constructor dialog {} {
grid columnconfigure $w.desc 1 -weight 1
pack $w.desc -anchor nw -fill x -pady 5 -padx 5
labelframe $w.action -text [mc "Further Action"]
${NS}::labelframe $w.action -text [mc "Further Action"]
radiobutton $w.action.fetch \
${NS}::radiobutton $w.action.fetch \
-text [mc "Fetch Immediately"] \
-value fetch \
-variable @opt_action
pack $w.action.fetch -anchor nw
radiobutton $w.action.push \
${NS}::radiobutton $w.action.push \
-text [mc "Initialize Remote Repository and Push"] \
-value push \
-variable @opt_action
pack $w.action.push -anchor nw
radiobutton $w.action.none \
${NS}::radiobutton $w.action.none \
-text [mc "Do Nothing Else Now"] \
-value none \
-variable @opt_action
@@ -85,6 +83,7 @@ constructor dialog {} {
bind $w <Visibility> [cb _visible]
bind $w <Key-Escape> [list destroy $w]
bind $w <Key-Return> [cb _add]\;break
wm deiconify $top
tkwait window $w
}

View File

@@ -23,34 +23,40 @@ field full_cache
field cached
constructor dialog {} {
global all_remotes M1B
global all_remotes M1B use_ttk NS
make_toplevel top w
make_dialog top w
wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch Remotely"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
}
label $w.header -text [mc "Delete Branch Remotely"] -font font_uibold
${NS}::label $w.header -text [mc "Delete Branch Remotely"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x
frame $w.buttons
button $w.buttons.delete -text [mc Delete] \
${NS}::frame $w.buttons
${NS}::button $w.buttons.delete -text [mc Delete] \
-default active \
-command [cb _delete]
pack $w.buttons.delete -side right
button $w.buttons.cancel -text [mc "Cancel"] \
${NS}::button $w.buttons.cancel -text [mc "Cancel"] \
-command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.dest -text [mc "From Repository"]
${NS}::labelframe $w.dest -text [mc "From Repository"]
if {$all_remotes ne {}} {
radiobutton $w.dest.remote_r \
${NS}::radiobutton $w.dest.remote_r \
-text [mc "Remote:"] \
-value remote \
-variable @urltype
eval tk_optionMenu $w.dest.remote_m @remote $all_remotes
if {$use_ttk} {
ttk::combobox $w.dest.remote_m -textvariable @remote \
-values $all_remotes -state readonly
} else {
eval tk_optionMenu $w.dest.remote_m @remote $all_remotes
}
grid $w.dest.remote_r $w.dest.remote_m -sticky w
if {[lsearch -sorted -exact $all_remotes origin] != -1} {
set remote origin
@@ -62,13 +68,11 @@ constructor dialog {} {
} else {
set urltype url
}
radiobutton $w.dest.url_r \
${NS}::radiobutton $w.dest.url_r \
-text [mc "Arbitrary Location:"] \
-value url \
-variable @urltype
entry $w.dest.url_t \
-borderwidth 1 \
-relief sunken \
${NS}::entry $w.dest.url_t \
-width 50 \
-textvariable @url \
-validate key \
@@ -81,33 +85,30 @@ constructor dialog {} {
grid columnconfigure $w.dest 1 -weight 1
pack $w.dest -anchor nw -fill x -pady 5 -padx 5
labelframe $w.heads -text [mc "Branches"]
listbox $w.heads.l \
${NS}::labelframe $w.heads -text [mc "Branches"]
slistbox $w.heads.l \
-height 10 \
-width 70 \
-listvariable @head_list \
-selectmode extended \
-yscrollcommand [list $w.heads.sby set]
scrollbar $w.heads.sby -command [list $w.heads.l yview]
-selectmode extended
frame $w.heads.footer
label $w.heads.footer.status \
${NS}::frame $w.heads.footer
${NS}::label $w.heads.footer.status \
-textvariable @status \
-anchor w \
-justify left
button $w.heads.footer.rescan \
${NS}::button $w.heads.footer.rescan \
-text [mc "Rescan"] \
-command [cb _rescan]
pack $w.heads.footer.status -side left -fill x
pack $w.heads.footer.rescan -side right
pack $w.heads.footer -side bottom -fill x
pack $w.heads.sby -side right -fill y
pack $w.heads.l -side left -fill both -expand 1
pack $w.heads -fill both -expand 1 -pady 5 -padx 5
labelframe $w.validate -text [mc "Delete Only If"]
radiobutton $w.validate.head_r \
${NS}::labelframe $w.validate -text [mc "Delete Only If"]
${NS}::radiobutton $w.validate.head_r \
-text [mc "Merged Into:"] \
-value head \
-variable @checktype
@@ -115,7 +116,7 @@ constructor dialog {} {
trace add variable @head_list write [cb _write_head_list]
trace add variable @check_head write [cb _write_check_head]
grid $w.validate.head_r $w.validate.head_m -sticky w
radiobutton $w.validate.always_r \
${NS}::radiobutton $w.validate.always_r \
-text [mc "Always (Do not perform merge checks)"] \
-value always \
-variable @checktype

View File

@@ -14,15 +14,16 @@ field smarktop
field smarkbot
constructor new {i_w i_text args} {
global use_ttk NS
set w $i_w
set ctext $i_text
frame $w
label $w.l -text [mc Find:]
${NS}::frame $w
${NS}::label $w.l -text [mc Find:]
entry $w.ent -textvariable ${__this}::searchstring -background lightgreen
button $w.bn -text [mc Next] -command [cb find_next]
button $w.bp -text [mc Prev] -command [cb find_prev]
checkbutton $w.cs -text [mc Case-Sensitive] \
${NS}::button $w.bn -text [mc Next] -command [cb find_next]
${NS}::button $w.bp -text [mc Prev] -command [cb find_prev]
${NS}::checkbutton $w.cs -text [mc Case-Sensitive] \
-variable ${__this}::casesensitive -command [cb _incrsearch]
pack $w.l -side left
pack $w.cs -side right

View File

@@ -2,6 +2,7 @@
# Copyright (C) 2006, 2007 Shawn Pearce
proc do_windows_shortcut {} {
global _gitworktree
set fn [tk_getSaveFile \
-parent . \
-title [append "[appname] ([reponame]): " [mc "Create Desktop Icon"]] \
@@ -15,7 +16,7 @@ proc do_windows_shortcut {} {
[info nameofexecutable] \
[file normalize $::argv0] \
] \
[file dirname [file normalize [gitdir]]]
[file normalize [$_gitworktree]]
} err]} {
error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"]
}
@@ -23,7 +24,7 @@ proc do_windows_shortcut {} {
}
proc do_cygwin_shortcut {} {
global argv0
global argv0 _gitworktree
if {[catch {
set desktop [exec cygpath \
@@ -56,7 +57,7 @@ proc do_cygwin_shortcut {} {
$sh -c \
"CHERE_INVOKING=1 source /etc/profile;[sq $me] &" \
] \
[file dirname [file normalize [gitdir]]]
[file normalize [$_gitworktree]]
} err]} {
error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"]
}

View File

@@ -15,7 +15,7 @@ proc find_ssh_key {} {
}
proc do_ssh_key {} {
global sshkey_title have_tk85 sshkey_fd
global sshkey_title have_tk85 sshkey_fd use_ttk NS
set w .sshkey_dialog
if {[winfo exists $w]} {
@@ -23,7 +23,7 @@ proc do_ssh_key {} {
return
}
toplevel $w
Dialog $w
wm transient $w .
set finfo [find_ssh_key]
@@ -35,9 +35,9 @@ proc do_ssh_key {} {
set gen_state disabled
}
frame $w.header -relief flat
label $w.header.lbl -textvariable sshkey_title -anchor w
button $w.header.gen -text [mc "Generate Key"] \
${NS}::frame $w.header
${NS}::label $w.header.lbl -textvariable sshkey_title -anchor w
${NS}::button $w.header.gen -text [mc "Generate Key"] \
-command [list make_ssh_key $w] -state $gen_state
pack $w.header.lbl -side left -expand 1 -fill x
pack $w.header.gen -side right
@@ -46,14 +46,16 @@ proc do_ssh_key {} {
text $w.contents -width 60 -height 10 -wrap char -relief sunken
pack $w.contents -fill both -expand 1
if {$have_tk85} {
$w.contents configure -inactiveselectbackground darkblue
set clr darkblue
if {$use_ttk} { set clr [ttk::style lookup . -selectbackground] }
$w.contents configure -inactiveselectbackground $clr
}
frame $w.buttons
button $w.buttons.close -text [mc Close] \
${NS}::frame $w.buttons
${NS}::button $w.buttons.close -text [mc Close] \
-default active -command [list destroy $w]
pack $w.buttons.close -side right
button $w.buttons.copy -text [mc "Copy To Clipboard"] \
${NS}::button $w.buttons.copy -text [mc "Copy To Clipboard"] \
-command [list tk_textCopy $w.contents]
pack $w.buttons.copy -side left
pack $w.buttons -side bottom -fill x -pady 5 -padx 5

View File

@@ -13,14 +13,16 @@ field units {}; # unit of progress
field meter {}; # current core git progress meter (if active)
constructor new {path} {
global use_ttk NS
set w $path
set w_l $w.l
set w_c $w.c
frame $w \
-borderwidth 1 \
-relief sunken
label $w_l \
${NS}::frame $w
if {!$use_ttk} {
$w configure -borderwidth 1 -relief sunken
}
${NS}::label $w_l \
-textvariable @status \
-anchor w \
-justify left
@@ -41,8 +43,8 @@ constructor two_line {path} {
set w_l $w.l
set w_c $w.c
frame $w
label $w_l \
${NS}::frame $w
${NS}::label $w_l \
-textvariable @status \
-anchor w \
-justify left

174
git-gui/lib/themed.tcl Normal file
View File

@@ -0,0 +1,174 @@
# Functions for supporting the use of themed Tk widgets in git-gui.
# Copyright (C) 2009 Pat Thoyts <patthoyts@users.sourceforge.net>
proc InitTheme {} {
# Create a color label style (bg can be overridden by widget option)
ttk::style layout Color.TLabel {
Color.Label.border -sticky news -children {
Color.label.fill -sticky news -children {
Color.Label.padding -sticky news -children {
Color.Label.label -sticky news}}}}
eval [linsert [ttk::style configure TLabel] 0 \
ttk::style configure Color.TLabel]
ttk::style configure Color.TLabel \
-borderwidth 0 -relief flat -padding 2
ttk::style map Color.TLabel -background {{} gold}
# We also need a padded label.
ttk::style configure Padded.TLabel \
-padding {5 5} -borderwidth 1 -relief solid
# We need a gold frame.
ttk::style layout Gold.TFrame {
Gold.Frame.border -sticky nswe -children {
Gold.Frame.fill -sticky nswe}}
ttk::style configure Gold.TFrame -background gold -relief flat
# listboxes should have a theme border so embed in ttk::frame
ttk::style layout SListbox.TFrame {
SListbox.Frame.Entry.field -sticky news -border true -children {
SListbox.Frame.padding -sticky news
}
}
}
proc gold_frame {w args} {
global use_ttk
if {$use_ttk} {
eval [linsert $args 0 ttk::frame $w -style Gold.TFrame]
} else {
eval [linsert $args 0 frame $w -background gold]
}
}
proc tlabel {w args} {
global use_ttk
if {$use_ttk} {
set cmd [list ttk::label $w -style Color.TLabel]
foreach {k v} $args {
switch -glob -- $k {
-activebackground {}
default { lappend cmd $k $v }
}
}
eval $cmd
} else {
eval [linsert $args 0 label $w]
}
}
# The padded label gets used in the about class.
proc paddedlabel {w args} {
global use_ttk
if {$use_ttk} {
eval [linsert $args 0 ttk::label $w -style Padded.TLabel]
} else {
eval [linsert $args 0 label $w \
-padx 5 -pady 5 \
-justify left \
-anchor w \
-borderwidth 1 \
-relief solid]
}
}
# Create a toplevel for use as a dialog.
# If available, sets the EWMH dialog hint and if ttk is enabled
# place a themed frame over the surface.
proc Dialog {w args} {
eval [linsert $args 0 toplevel $w -class Dialog]
pave_toplevel $w
return $w
}
# Tk toplevels are not themed - so pave it over with a themed frame to get
# the base color correct per theme.
proc pave_toplevel {w} {
global use_ttk
if {$use_ttk && ![winfo exists $w.!paving]} {
set paving [ttk::frame $w.!paving]
place $paving -x 0 -y 0 -relwidth 1 -relheight 1
lower $paving
}
}
# Create a scrolled listbox with appropriate border for the current theme.
# On many themes the border for a scrolled listbox needs to go around the
# listbox and the scrollbar.
proc slistbox {w args} {
global use_ttk NS
if {$use_ttk} {
set f [ttk::frame $w -style SListbox.TFrame -padding 2]
} else {
set f [frame $w -relief flat]
}
if {[catch {
if {$use_ttk} {
eval [linsert $args 0 listbox $f.list -relief flat \
-highlightthickness 0 -borderwidth 0]
} else {
eval [linsert $args 0 listbox $f.list]
}
${NS}::scrollbar $f.vs -command [list $f.list yview]
$f.list configure -yscrollcommand [list $f.vs set]
grid $f.list $f.vs -sticky news
grid rowconfigure $f 0 -weight 1
grid columnconfigure $f 0 -weight 1
bind $f.list <<ListboxSelect>> \
[list event generate $w <<ListboxSelect>>]
interp hide {} $w
interp alias {} $w {} $f.list
} err]} {
destroy $f
return -code error $err
}
return $w
}
# fetch the background color from a widget.
proc get_bg_color {w} {
global use_ttk
if {$use_ttk} {
set bg [ttk::style lookup [winfo class $w] -background]
} else {
set bg [$w cget -background]
}
return $bg
}
# ttk::spinbox didn't get added until 8.6
proc tspinbox {w args} {
global use_ttk
if {$use_ttk && [llength [info commands ttk::spinbox]] > 0} {
eval [linsert $args 0 ttk::spinbox $w]
} else {
eval [linsert $args 0 spinbox $w]
}
}
# Tk 8.6 provides a standard font selection dialog. This uses the native
# dialogs on Windows and MacOSX or a standard Tk dialog on X11.
proc tchoosefont {w title familyvar sizevar} {
if {[package vsatisfies [package provide Tk] 8.6]} {
upvar #0 $familyvar family
upvar #0 $sizevar size
tk fontchooser configure -parent $w -title $title \
-font [list $family $size] \
-command [list on_choosefont $familyvar $sizevar]
tk fontchooser show
} else {
choose_font::pick $w $title $familyvar $sizevar
}
}
# Called when the Tk 8.6 fontchooser selects a font.
proc on_choosefont {familyvar sizevar font} {
upvar #0 $familyvar family
upvar #0 $sizevar size
set font [font actual $font]
set family [dict get $font -family]
set size [dict get $font -size]
}
# Local variables:
# mode: tcl
# indent-tabs-mode: t
# tab-width: 4
# End:

View File

@@ -16,53 +16,50 @@ field ask_branch 0; # ask for a revision
field ask_args 0; # ask for additional args
constructor dialog {} {
global repo_config
global repo_config use_ttk NS
make_toplevel top w
make_dialog top w
wm title $top [append "[appname] ([reponame]): " [mc "Add Tool"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
wm transient $top .
}
label $w.header -text [mc "Add New Tool Command"] -font font_uibold
${NS}::label $w.header -text [mc "Add New Tool Command"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x
frame $w.buttons
checkbutton $w.buttons.global \
${NS}::frame $w.buttons
${NS}::checkbutton $w.buttons.global \
-text [mc "Add globally"] \
-variable @add_global
pack $w.buttons.global -side left -padx 5
button $w.buttons.create -text [mc Add] \
${NS}::button $w.buttons.create -text [mc Add] \
-default active \
-command [cb _add]
pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc Cancel] \
${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.desc -text [mc "Tool Details"]
${NS}::labelframe $w.desc -text [mc "Tool Details"]
label $w.desc.name_cmnt -anchor w\
${NS}::label $w.desc.name_cmnt -anchor w\
-text [mc "Use '/' separators to create a submenu tree:"]
grid x $w.desc.name_cmnt -sticky we -padx {0 5} -pady {0 2}
label $w.desc.name_l -text [mc "Name:"]
${NS}::label $w.desc.name_l -text [mc "Name:"]
set w_name $w.desc.name_t
entry $w_name \
-borderwidth 1 \
-relief sunken \
${NS}::entry $w_name \
-width 40 \
-textvariable @name \
-validate key \
-validatecommand [cb _validate_name %d %S]
grid $w.desc.name_l $w_name -sticky we -padx {0 5}
label $w.desc.cmd_l -text [mc "Command:"]
${NS}::label $w.desc.cmd_l -text [mc "Command:"]
set w_cmd $w.desc.cmd_t
entry $w_cmd \
-borderwidth 1 \
-relief sunken \
${NS}::entry $w_cmd \
-width 40 \
-textvariable @command
grid $w.desc.cmd_l $w_cmd -sticky we -padx {0 5} -pady {0 3}
@@ -70,30 +67,30 @@ constructor dialog {} {
grid columnconfigure $w.desc 1 -weight 1
pack $w.desc -anchor nw -fill x -pady 5 -padx 5
checkbutton $w.confirm \
${NS}::checkbutton $w.confirm \
-text [mc "Show a dialog before running"] \
-variable @confirm -command [cb _check_enable_dlg]
labelframe $w.dlg -labelwidget $w.confirm
${NS}::labelframe $w.dlg -labelwidget $w.confirm
checkbutton $w.dlg.askbranch \
${NS}::checkbutton $w.dlg.askbranch \
-text [mc "Ask the user to select a revision (sets \$REVISION)"] \
-variable @ask_branch -state disabled
pack $w.dlg.askbranch -anchor w -padx 15
checkbutton $w.dlg.askargs \
${NS}::checkbutton $w.dlg.askargs \
-text [mc "Ask the user for additional arguments (sets \$ARGS)"] \
-variable @ask_args -state disabled
pack $w.dlg.askargs -anchor w -padx 15
pack $w.dlg -anchor nw -fill x -pady {0 8} -padx 5
checkbutton $w.noconsole \
${NS}::checkbutton $w.noconsole \
-text [mc "Don't show the command output window"] \
-variable @no_console
pack $w.noconsole -anchor w -padx 5
checkbutton $w.needsfile \
${NS}::checkbutton $w.needsfile \
-text [mc "Run only if a diff is selected (\$FILENAME not empty)"] \
-variable @needs_file
pack $w.needsfile -anchor w -padx 5
@@ -182,40 +179,38 @@ field w ; # widget path
field w_names ; # name list
constructor dialog {} {
global repo_config global_config system_config
global repo_config global_config system_config use_ttk NS
load_config 1
make_toplevel top w
make_dialog top w
wm title $top [append "[appname] ([reponame]): " [mc "Remove Tool"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
wm transient $top .
}
label $w.header -text [mc "Remove Tool Commands"] -font font_uibold
${NS}::label $w.header -text [mc "Remove Tool Commands"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x
frame $w.buttons
button $w.buttons.create -text [mc Remove] \
${NS}::frame $w.buttons
${NS}::button $w.buttons.create -text [mc Remove] \
-default active \
-command [cb _remove]
pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc Cancel] \
${NS}::button $w.buttons.cancel -text [mc Cancel] \
-command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
frame $w.list
${NS}::frame $w.list
set w_names $w.list.l
listbox $w_names \
slistbox $w_names \
-height 10 \
-width 30 \
-selectmode extended \
-exportselection false \
-yscrollcommand [list $w.list.sby set]
scrollbar $w.list.sby -command [list $w.list.l yview]
pack $w.list.sby -side right -fill y
-exportselection false
pack $w.list.l -side left -fill both -expand 1
pack $w.list -fill both -expand 1 -pady 5 -padx 5
@@ -232,7 +227,7 @@ constructor dialog {} {
}
if {$local_cnt > 0} {
label $w.colorlbl -foreground blue \
${NS}::label $w.colorlbl -foreground blue \
-text [mc "(Blue denotes repository-local tools)"]
pack $w.colorlbl -fill x -pady 5 -padx 5
}
@@ -277,14 +272,14 @@ field is_ok 0; # ok to start
field argstr {}; # arguments
constructor dialog {fullname} {
global M1B
global M1B use_ttk NS
set title [get_config "guitool.$fullname.title"]
if {$title eq {}} {
regsub {/} $fullname { / } title
}
make_toplevel top w -autodelete 0
make_dialog top w -autodelete 0
wm title $top [append "[appname] ([reponame]): " $title]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
@@ -297,7 +292,7 @@ constructor dialog {fullname} {
set prompt [mc "Run Command: %s" $command]
}
label $w.header -text $prompt -font font_uibold
${NS}::label $w.header -text $prompt -font font_uibold -anchor center
pack $w.header -side top -fill x
set argprompt [get_config "guitool.$fullname.argprompt"]
@@ -311,12 +306,10 @@ constructor dialog {fullname} {
set argprompt [mc "Arguments"]
}
labelframe $w.arg -text $argprompt
${NS}::labelframe $w.arg -text $argprompt
set w_args $w.arg.txt
entry $w_args \
-borderwidth 1 \
-relief sunken \
${NS}::entry $w_args \
-width 40 \
-textvariable @argstr
pack $w_args -padx 5 -pady 5 -fill both
@@ -337,18 +330,18 @@ constructor dialog {fullname} {
pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5
}
frame $w.buttons
${NS}::frame $w.buttons
if {$is_ask_revs} {
button $w.buttons.visualize \
${NS}::button $w.buttons.visualize \
-text [mc Visualize] \
-command [cb _visualize]
pack $w.buttons.visualize -side left
}
button $w.buttons.ok \
${NS}::button $w.buttons.ok \
-text [mc OK] \
-command [cb _start]
pack $w.buttons.ok -side right
button $w.buttons.cancel \
${NS}::button $w.buttons.cancel \
-text [mc "Cancel"] \
-command [cb _cancel]
pack $w.buttons.cancel -side right -padx 5

View File

@@ -91,50 +91,55 @@ trace add variable push_remote write \
proc do_push_anywhere {} {
global all_remotes current_branch
global push_urltype push_remote push_url push_thin push_tags
global push_force
global push_force use_ttk NS
set w .push_setup
toplevel $w
wm withdraw $w
wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
pave_toplevel $w
label $w.header -text [mc "Push Branches"] -font font_uibold
${NS}::label $w.header -text [mc "Push Branches"] \
-font font_uibold -anchor center
pack $w.header -side top -fill x
frame $w.buttons
button $w.buttons.create -text [mc Push] \
${NS}::frame $w.buttons
${NS}::button $w.buttons.create -text [mc Push] \
-default active \
-command [list start_push_anywhere_action $w]
pack $w.buttons.create -side right
button $w.buttons.cancel -text [mc "Cancel"] \
${NS}::button $w.buttons.cancel -text [mc "Cancel"] \
-default normal \
-command [list destroy $w]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.source -text [mc "Source Branches"]
listbox $w.source.l \
${NS}::labelframe $w.source -text [mc "Source Branches"]
slistbox $w.source.l \
-height 10 \
-width 70 \
-selectmode extended \
-yscrollcommand [list $w.source.sby set]
-selectmode extended
foreach h [load_all_heads] {
$w.source.l insert end $h
if {$h eq $current_branch} {
$w.source.l select set end
}
}
scrollbar $w.source.sby -command [list $w.source.l yview]
pack $w.source.sby -side right -fill y
pack $w.source.l -side left -fill both -expand 1
pack $w.source -fill both -expand 1 -pady 5 -padx 5
labelframe $w.dest -text [mc "Destination Repository"]
${NS}::labelframe $w.dest -text [mc "Destination Repository"]
if {$all_remotes ne {}} {
radiobutton $w.dest.remote_r \
${NS}::radiobutton $w.dest.remote_r \
-text [mc "Remote:"] \
-value remote \
-variable push_urltype
eval tk_optionMenu $w.dest.remote_m push_remote $all_remotes
if {$use_ttk} {
ttk::combobox $w.dest.remote_m -textvariable push_remote \
-values $all_remotes
} else {
eval tk_optionMenu $w.dest.remote_m push_remote $all_remotes
}
grid $w.dest.remote_r $w.dest.remote_m -sticky w
if {[lsearch -sorted -exact $all_remotes origin] != -1} {
set push_remote origin
@@ -145,13 +150,11 @@ proc do_push_anywhere {} {
} else {
set push_urltype url
}
radiobutton $w.dest.url_r \
${NS}::radiobutton $w.dest.url_r \
-text [mc "Arbitrary Location:"] \
-value url \
-variable push_urltype
entry $w.dest.url_t \
-borderwidth 1 \
-relief sunken \
${NS}::entry $w.dest.url_t \
-width 50 \
-textvariable push_url \
-validate key \
@@ -166,16 +169,16 @@ proc do_push_anywhere {} {
grid columnconfigure $w.dest 1 -weight 1
pack $w.dest -anchor nw -fill x -pady 5 -padx 5
labelframe $w.options -text [mc "Transfer Options"]
checkbutton $w.options.force \
${NS}::labelframe $w.options -text [mc "Transfer Options"]
${NS}::checkbutton $w.options.force \
-text [mc "Force overwrite existing branch (may discard changes)"] \
-variable push_force
grid $w.options.force -columnspan 2 -sticky w
checkbutton $w.options.thin \
${NS}::checkbutton $w.options.thin \
-text [mc "Use thin pack (for slow network connections)"] \
-variable push_thin
grid $w.options.thin -columnspan 2 -sticky w
checkbutton $w.options.tags \
${NS}::checkbutton $w.options.tags \
-text [mc "Include tags"] \
-variable push_tags
grid $w.options.tags -columnspan 2 -sticky w
@@ -191,5 +194,6 @@ proc do_push_anywhere {} {
bind $w <Key-Escape> "destroy $w"
bind $w <Key-Return> [list start_push_anywhere_action $w]
wm title $w [append "[appname] ([reponame]): " [mc "Push"]]
wm deiconify $w
tkwait window $w
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1656,6 +1656,7 @@ use File::Path qw/mkpath/;
use File::Copy qw/copy/;
use IPC::Open3;
use Memoize; # core since 5.8.0, Jul 2002
use Memoize::Storable;
my ($_gc_nr, $_gc_period);
@@ -3116,10 +3117,39 @@ sub has_no_changes {
command_oneline("rev-parse", "$commit~1^{tree}"));
}
BEGIN {
memoize 'lookup_svn_merge';
memoize 'check_cherry_pick';
memoize 'has_no_changes';
# The GIT_DIR environment variable is not always set until after the command
# line arguments are processed, so we can't memoize in a BEGIN block.
{
my $memoized = 0;
sub memoize_svn_mergeinfo_functions {
return if $memoized;
$memoized = 1;
my $cache_path = "$ENV{GIT_DIR}/svn/.caches/";
mkpath([$cache_path]) unless -d $cache_path;
tie my %lookup_svn_merge_cache => 'Memoize::Storable',
"$cache_path/lookup_svn_merge.db", 'nstore';
memoize 'lookup_svn_merge',
SCALAR_CACHE => 'FAULT',
LIST_CACHE => ['HASH' => \%lookup_svn_merge_cache],
;
tie my %check_cherry_pick_cache => 'Memoize::Storable',
"$cache_path/check_cherry_pick.db", 'nstore';
memoize 'check_cherry_pick',
SCALAR_CACHE => 'FAULT',
LIST_CACHE => ['HASH' => \%check_cherry_pick_cache],
;
tie my %has_no_changes_cache => 'Memoize::Storable',
"$cache_path/has_no_changes.db", 'nstore';
memoize 'has_no_changes',
SCALAR_CACHE => ['HASH' => \%has_no_changes_cache],
LIST_CACHE => 'FAULT',
;
}
}
sub parents_exclude {
@@ -3163,6 +3193,8 @@ sub find_extra_svn_parents {
my ($self, $ed, $mergeinfo, $parents) = @_;
# aha! svk:merge property changed...
memoize_svn_mergeinfo_functions();
# We first search for merged tips which are not in our
# history. Then, we figure out which git revisions are in
# that tip, but not this revision. If all of those revisions

2
git.c
View File

@@ -317,7 +317,7 @@ static void handle_internal_command(int argc, const char **argv)
{ "fsck-objects", cmd_fsck, RUN_SETUP },
{ "gc", cmd_gc, RUN_SETUP },
{ "get-tar-commit-id", cmd_get_tar_commit_id },
{ "grep", cmd_grep, USE_PAGER },
{ "grep", cmd_grep, RUN_SETUP | USE_PAGER },
{ "hash-object", cmd_hash_object },
{ "help", cmd_help },
{ "index-pack", cmd_index_pack },

View File

@@ -2783,7 +2783,7 @@ proc about {} {
message $w.m -text [mc "
Gitk - a commit viewer for git
Copyright \u00a9 2005-2009 Paul Mackerras
Copyright © 2005-2009 Paul Mackerras
Use and redistribute under the terms of the GNU General Public License"] \
-justify center -aspect 400 -border 2 -bg white -relief groove

129
gitweb/Makefile Normal file
View File

@@ -0,0 +1,129 @@
# The default target of this Makefile is...
all::
# Define V=1 to have a more verbose compile.
#
# Define JSMIN to point to JavaScript minifier that functions as
# a filter to have gitweb.js minified.
#
prefix ?= $(HOME)
bindir ?= $(prefix)/bin
RM ?= rm -f
# JavaScript minifier invocation that can function as filter
JSMIN ?=
# default configuration for gitweb
GITWEB_CONFIG = gitweb_config.perl
GITWEB_CONFIG_SYSTEM = /etc/gitweb.conf
GITWEB_HOME_LINK_STR = projects
GITWEB_SITENAME =
GITWEB_PROJECTROOT = /pub/git
GITWEB_PROJECT_MAXDEPTH = 2007
GITWEB_EXPORT_OK =
GITWEB_STRICT_EXPORT =
GITWEB_BASE_URL =
GITWEB_LIST =
GITWEB_HOMETEXT = indextext.html
GITWEB_CSS = gitweb.css
GITWEB_LOGO = git-logo.png
GITWEB_FAVICON = git-favicon.png
ifdef JSMIN
GITWEB_JS = gitweb.min.js
else
GITWEB_JS = gitweb.js
endif
GITWEB_SITE_HEADER =
GITWEB_SITE_FOOTER =
# include user config
-include ../config.mak.autogen
-include ../config.mak
# determine version
../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
$(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) GIT-VERSION-FILE
-include ../GIT-VERSION-FILE
### Build rules
SHELL_PATH ?= $(SHELL)
PERL_PATH ?= /usr/bin/perl
# Shell quote;
bindir_SQ = $(subst ','\'',$(bindir)) #'
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) #'
PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) #'
# Quiet generation (unless V=1)
QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
QUIET_SUBDIR1 =
ifneq ($(findstring $(MAKEFLAGS),w),w)
PRINT_DIR = --no-print-directory
else # "make -w"
NO_SUBDIR = :
endif
ifneq ($(findstring $(MAKEFLAGS),s),s)
ifndef V
QUIET = @
QUIET_GEN = $(QUIET)echo ' ' GEN $@;
QUIET_SUBDIR0 = +@subdir=
QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
$(MAKE) $(PRINT_DIR) -C $$subdir
export V
export QUIET
export QUIET_GEN
export QUIET_SUBDIR0
export QUIET_SUBDIR1
endif
endif
all:: gitweb.cgi
ifdef JSMIN
FILES=gitweb.cgi gitweb.min.js
gitweb.cgi: gitweb.perl gitweb.min.js
else # !JSMIN
FILES=gitweb.cgi
gitweb.cgi: gitweb.perl
endif # JSMIN
gitweb.cgi:
$(QUIET_GEN)$(RM) $@ $@+ && \
sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \
-e 's|++GIT_VERSION++|$(GIT_VERSION)|g' \
-e 's|++GIT_BINDIR++|$(bindir)|g' \
-e 's|++GITWEB_CONFIG++|$(GITWEB_CONFIG)|g' \
-e 's|++GITWEB_CONFIG_SYSTEM++|$(GITWEB_CONFIG_SYSTEM)|g' \
-e 's|++GITWEB_HOME_LINK_STR++|$(GITWEB_HOME_LINK_STR)|g' \
-e 's|++GITWEB_SITENAME++|$(GITWEB_SITENAME)|g' \
-e 's|++GITWEB_PROJECTROOT++|$(GITWEB_PROJECTROOT)|g' \
-e 's|"++GITWEB_PROJECT_MAXDEPTH++"|$(GITWEB_PROJECT_MAXDEPTH)|g' \
-e 's|++GITWEB_EXPORT_OK++|$(GITWEB_EXPORT_OK)|g' \
-e 's|++GITWEB_STRICT_EXPORT++|$(GITWEB_STRICT_EXPORT)|g' \
-e 's|++GITWEB_BASE_URL++|$(GITWEB_BASE_URL)|g' \
-e 's|++GITWEB_LIST++|$(GITWEB_LIST)|g' \
-e 's|++GITWEB_HOMETEXT++|$(GITWEB_HOMETEXT)|g' \
-e 's|++GITWEB_CSS++|$(GITWEB_CSS)|g' \
-e 's|++GITWEB_LOGO++|$(GITWEB_LOGO)|g' \
-e 's|++GITWEB_FAVICON++|$(GITWEB_FAVICON)|g' \
-e 's|++GITWEB_JS++|$(GITWEB_JS)|g' \
-e 's|++GITWEB_SITE_HEADER++|$(GITWEB_SITE_HEADER)|g' \
-e 's|++GITWEB_SITE_FOOTER++|$(GITWEB_SITE_FOOTER)|g' \
$< >$@+ && \
chmod +x $@+ && \
mv $@+ $@
ifdef JSMIN
gitweb.min.js: gitweb.js
$(QUIET_GEN)$(JSMIN) <$< >$@
endif # JSMIN
clean:
$(RM) $(FILES)
.PHONY: all clean .FORCE-GIT-VERSION-FILE

View File

@@ -174,7 +174,7 @@ not include variables usually directly set during build):
Base URL for relative URLs in pages generated by gitweb,
(e.g. $logo, $favicon, @stylesheets if they are relative URLs),
needed and used only for URLs with nonempty PATH_INFO via
<base href="$base_url>. Usually gitweb sets its value correctly,
<base href="$base_url">. Usually gitweb sets its value correctly,
and there is no need to set this variable, e.g. to $my_uri or "/".
* $home_link
Target of the home link on top of all pages (the first part of view
@@ -228,6 +228,11 @@ not include variables usually directly set during build):
repositories from launching cross-site scripting (XSS) attacks. Set this
to true if you don't trust the content of your repositories. The default
is false.
* $maxload
Used to set the maximum load that we will still respond to gitweb queries.
If server load exceed this value then return "503 Service Unavaliable" error.
Server load is taken to be 0 if gitweb cannot determine its value. Set it to
undefined value to turn it off. The default is 300.
Projects list file format

View File

@@ -221,6 +221,12 @@ our %avatar_size = (
'double' => 32
);
# Used to set the maximum load that we will still respond to gitweb queries.
# If server load exceed this value then return "503 server busy" error.
# If gitweb cannot determined server load, it is taken to be 0.
# Leave it undefined (or set to 'undef') to turn off load checking.
our $maxload = 300;
# You define site-wide feature defaults here; override them with
# $GITWEB_CONFIG as necessary.
our %feature = (
@@ -551,12 +557,38 @@ if (-e $GITWEB_CONFIG) {
do $GITWEB_CONFIG_SYSTEM if -e $GITWEB_CONFIG_SYSTEM;
}
# Get loadavg of system, to compare against $maxload.
# Currently it requires '/proc/loadavg' present to get loadavg;
# if it is not present it returns 0, which means no load checking.
sub get_loadavg {
if( -e '/proc/loadavg' ){
open my $fd, '<', '/proc/loadavg'
or return 0;
my @load = split(/\s+/, scalar <$fd>);
close $fd;
# The first three columns measure CPU and IO utilization of the last one,
# five, and 10 minute periods. The fourth column shows the number of
# currently running processes and the total number of processes in the m/n
# format. The last column displays the last process ID used.
return $load[0] || 0;
}
# additional checks for load average should go here for things that don't export
# /proc/loadavg
return 0;
}
# version of the core git binary
our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown";
$number_of_git_cmds++;
$projects_list ||= $projectroot;
if (defined $maxload && get_loadavg() > $maxload) {
die_error(503, "The load average on the server is too high");
}
# ======================================================================
# input validation and dispatch
@@ -1298,7 +1330,6 @@ sub chop_str {
$str =~ m/^(.*?)($begre)$/;
my ($lead, $body) = ($1, $2);
if (length($lead) > 4) {
$body =~ s/^[^;]*;// if ($lead =~ m/&[^;]*$/);
$lead = " ...";
}
return "$lead$body";
@@ -1309,8 +1340,6 @@ sub chop_str {
$str =~ m/^(.*?)($begre)$/;
my ($mid, $right) = ($1, $2);
if (length($mid) > 5) {
$left =~ s/&[^;]*$//;
$right =~ s/^[^;]*;// if ($mid =~ m/&[^;]*$/);
$mid = " ... ";
}
return "$left$mid$right";
@@ -1320,7 +1349,6 @@ sub chop_str {
my $body = $1;
my $tail = $2;
if (length($tail) > 4) {
$body =~ s/&[^;]*$//;
$tail = "... ";
}
return "$body$tail";
@@ -3222,7 +3250,7 @@ EOF
print "</head>\n" .
"<body>\n";
if (-f $site_header) {
if (defined $site_header && -f $site_header) {
insert_file($site_header);
}
@@ -3323,12 +3351,13 @@ sub git_footer_html {
print "</div>\n"; # class="page_footer"
}
if (-f $site_footer) {
if (defined $site_footer && -f $site_footer) {
insert_file($site_footer);
}
print qq!<script type="text/javascript" src="$javascript"></script>\n!;
if ($action eq 'blame_incremental') {
if (defined $action &&
$action eq 'blame_incremental') {
print qq!<script type="text/javascript">\n!.
qq!startBlame("!. href(action=>"blame_data", -replay=>1) .qq!",\n!.
qq! "!. href() .qq!");\n!.
@@ -3354,22 +3383,33 @@ sub git_footer_html {
# 500: The server isn't configured properly, or
# an internal error occurred (e.g. failed assertions caused by bugs), or
# an unknown error occurred (e.g. the git binary died unexpectedly).
# 503: The server is currently unavailable (because it is overloaded,
# or down for maintenance). Generally, this is a temporary state.
sub die_error {
my $status = shift || 500;
my $error = shift || "Internal server error";
my $extra = shift;
my %http_responses = (400 => '400 Bad Request',
403 => '403 Forbidden',
404 => '404 Not Found',
500 => '500 Internal Server Error');
my %http_responses = (
400 => '400 Bad Request',
403 => '403 Forbidden',
404 => '404 Not Found',
500 => '500 Internal Server Error',
503 => '503 Service Unavailable',
);
git_header_html($http_responses{$status});
print <<EOF;
<div class="page_body">
<br /><br />
$status - $error
<br />
</div>
EOF
if (defined $extra) {
print "<hr />\n" .
"$extra\n";
}
print "</div>\n";
git_footer_html();
exit;
}
@@ -3471,14 +3511,21 @@ sub git_print_header_div {
}
sub print_local_time {
print format_local_time(@_);
}
sub format_local_time {
my $localtime = '';
my %date = @_;
if ($date{'hour_local'} < 6) {
printf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
$localtime .= sprintf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
$date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
} else {
printf(" (%02d:%02d %s)",
$localtime .= sprintf(" (%02d:%02d %s)",
$date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
}
return $localtime;
}
# Outputs the author name and date in long form
@@ -4302,17 +4349,24 @@ sub fill_project_list_info {
# print 'sort by' <th> element, generating 'sort by $name' replay link
# if that order is not selected
sub print_sort_th {
print format_sort_th(@_);
}
sub format_sort_th {
my ($name, $order, $header) = @_;
my $sort_th = "";
$header ||= ucfirst($name);
if ($order eq $name) {
print "<th>$header</th>\n";
$sort_th .= "<th>$header</th>\n";
} else {
print "<th>" .
$cgi->a({-href => href(-replay=>1, order=>$name),
-class => "header"}, $header) .
"</th>\n";
$sort_th .= "<th>" .
$cgi->a({-href => href(-replay=>1, order=>$name),
-class => "header"}, $header) .
"</th>\n";
}
return $sort_th;
}
sub git_project_list_body {
@@ -4743,7 +4797,7 @@ sub git_project_list {
}
git_header_html();
if (-f $home_text) {
if (defined $home_text && -f $home_text) {
print "<div class=\"index_include\">\n";
insert_file($home_text);
print "</div>\n";

5
grep.c
View File

@@ -57,11 +57,8 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
p->word_regexp = opt->word_regexp;
p->ignore_case = opt->ignore_case;
p->fixed = opt->fixed;
if (opt->fixed)
p->fixed = 1;
if (opt->regflags & REG_ICASE)
p->fixed = 0;
if (p->fixed)
return;

View File

@@ -213,7 +213,7 @@ static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
int ch;
len = next_quote_pos(p, maxlen);
if (len == maxlen || !p[len])
if (len == maxlen || (maxlen < 0 && !p[len]))
break;
if (!no_dq && p == name)
@@ -223,6 +223,8 @@ static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
EMIT('\\');
p += len;
ch = (unsigned char)*p++;
if (maxlen >= 0)
maxlen -= len + 1;
if (sq_lookup[ch] >= ' ') {
EMIT(sq_lookup[ch]);
} else {

View File

@@ -26,7 +26,7 @@ static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int reall
#define CACHE_EXT(s) ( (s[0]<<24)|(s[1]<<16)|(s[2]<<8)|(s[3]) )
#define CACHE_EXT_TREE 0x54524545 /* "TREE" */
#define CACHE_EXT_RESOLVE_UNDO 0x52455543 /* "REUN" */
#define CACHE_EXT_RESOLVE_UNDO 0x52455543 /* "REUC" */
struct index_state the_index;

View File

@@ -53,7 +53,7 @@ void resolve_undo_write(struct strbuf *sb, struct string_list *resolve_undo)
for_each_string_list(write_one, resolve_undo, sb);
}
struct string_list *resolve_undo_read(void *data, unsigned long size)
struct string_list *resolve_undo_read(const char *data, unsigned long size)
{
struct string_list *resolve_undo;
size_t len;
@@ -93,7 +93,7 @@ struct string_list *resolve_undo_read(void *data, unsigned long size)
continue;
if (size < 20)
goto error;
hashcpy(ui->sha1[i], data);
hashcpy(ui->sha1[i], (const unsigned char *)data);
size -= 20;
data += 20;
}

View File

@@ -8,7 +8,7 @@ struct resolve_undo_info {
extern void record_resolve_undo(struct index_state *, struct cache_entry *);
extern void resolve_undo_write(struct strbuf *, struct string_list *);
extern struct string_list *resolve_undo_read(void *, unsigned long);
extern struct string_list *resolve_undo_read(const char *, unsigned long);
extern void resolve_undo_clear_index(struct index_state *);
extern int unmerge_index_entry_at(struct index_state *, int);
extern void unmerge_index(struct index_state *, const char **);

View File

@@ -25,6 +25,7 @@ our \$favicon = 'file:///$TEST_DIRECTORY/../gitweb/git-favicon.png';
our \$projects_list = '';
our \$export_ok = '';
our \$strict_export = '';
our \$maxload = undef;
EOF

View File

@@ -25,7 +25,7 @@ for_each_name () {
for name in \
Name "Name and a${LF}LF" "Name and an${HT}HT" "Name${DQ}" \
"$FN$HT$GN" "$FN$LF$GN" "$FN $GN" "$FN$GN" "$FN$DQ$GN" \
"With SP in it"
"With SP in it" "caractère spécial/file"
do
eval "$1"
done
@@ -33,6 +33,7 @@ for_each_name () {
test_expect_success setup '
mkdir "caractère spécial" &&
for_each_name "echo initial >\"\$name\""
git add . &&
git commit -q -m Initial &&
@@ -50,6 +51,7 @@ Name
"Name and an\tHT"
"Name\""
With SP in it
"caract\303\250re sp\303\251cial/file"
"\346\277\261\351\207\216\t\347\264\224"
"\346\277\261\351\207\216\n\347\264\224"
"\346\277\261\351\207\216 \347\264\224"
@@ -63,6 +65,7 @@ Name
"Name and an\tHT"
"Name\""
With SP in it
caractère spécial/file
"濱野\t純"
"濱野\n純"
濱野 純
@@ -97,6 +100,13 @@ test_expect_success 'check fully quoted output from diff-tree' '
'
test_expect_success 'check fully quoted output from ls-tree' '
git ls-tree --name-only -r HEAD >current &&
test_cmp expect.quoted current
'
test_expect_success 'setting core.quotepath' '
git config --bool core.quotepath false
@@ -130,4 +140,11 @@ test_expect_success 'check fully quoted output from diff-tree' '
'
test_expect_success 'check fully quoted output from ls-tree' '
git ls-tree --name-only -r HEAD >current &&
test_cmp expect.raw current
'
test_done

View File

@@ -189,6 +189,16 @@ test_expect_success 'git archive --format=zip with --output' \
'git archive --format=zip --output=d2.zip HEAD &&
test_cmp d.zip d2.zip'
test_expect_success 'git archive with --output, inferring format' '
git archive --output=d3.zip HEAD &&
test_cmp d.zip d3.zip
'
test_expect_success 'git archive with --output, override inferred format' '
git archive --format=tar --output=d4.zip HEAD &&
test_cmp b.tar d4.zip
'
$UNZIP -v >/dev/null 2>&1
if [ $? -eq 127 ]; then
say "Skipping ZIP tests, because unzip was not found"

View File

@@ -16,7 +16,9 @@ test_expect_success \
perl -e "print \"a\" x 4096;" > a &&
perl -e "print \"b\" x 4096;" > b &&
perl -e "print \"c\" x 4096;" > c &&
git update-index --add a b c &&
test-genrandom "seed a" 2097152 > a_big &&
test-genrandom "seed b" 2097152 > b_big &&
git update-index --add a a_big b b_big c &&
cat c >d && echo foo >>d && git update-index --add d &&
tree=`git write-tree` &&
commit=`git commit-tree $tree </dev/null` && {
@@ -280,26 +282,8 @@ test_expect_success \
:'
test_expect_success \
'fake a SHA1 hash collision' \
'test -f .git/objects/c8/2de19312b6c3695c0c18f70709a6c535682a67 &&
cp -f .git/objects/9d/235ed07cd19811a6ceb342de82f190e49c9f68 \
.git/objects/c8/2de19312b6c3695c0c18f70709a6c535682a67'
test_expect_success \
'make sure index-pack detects the SHA1 collision' \
'test_must_fail git index-pack -o bad.idx test-3.pack 2>msg &&
grep "SHA1 COLLISION FOUND" msg'
test_expect_success \
'honor pack.packSizeLimit' \
'git config pack.packSizeLimit 200 &&
packname_4=$(git pack-objects test-4 <obj-list) &&
test 3 = $(ls test-4-*.pack | wc -l)'
test_expect_success 'unpacking with --strict' '
git config --unset pack.packsizelimit &&
for j in a b c d e f g
do
for i in 0 1 2 3 4 5 6 7 8 9
@@ -392,10 +376,42 @@ test_expect_success 'index-pack with --strict' '
)
'
test_expect_success 'tolerate absurdly small packsizelimit' '
git config pack.packSizeLimit 2 &&
packname_9=$(git pack-objects test-9 <obj-list) &&
test $(wc -l <obj-list) = $(ls test-9-*.pack | wc -l)
test_expect_success 'honor pack.packSizeLimit' '
git config pack.packSizeLimit 3m &&
packname_10=$(git pack-objects test-10 <obj-list) &&
test 2 = $(ls test-10-*.pack | wc -l)
'
test_expect_success 'verify resulting packs' '
git verify-pack test-10-*.pack
'
test_expect_success 'tolerate packsizelimit smaller than biggest object' '
git config pack.packSizeLimit 1 &&
packname_11=$(git pack-objects test-11 <obj-list) &&
test 3 = $(ls test-11-*.pack | wc -l)
'
test_expect_success 'verify resulting packs' '
git verify-pack test-11-*.pack
'
#
# WARNING!
#
# The following test is destructive. Please keep the next
# two tests at the end of this file.
#
test_expect_success \
'fake a SHA1 hash collision' \
'test -f .git/objects/c8/2de19312b6c3695c0c18f70709a6c535682a67 &&
cp -f .git/objects/9d/235ed07cd19811a6ceb342de82f190e49c9f68 \
.git/objects/c8/2de19312b6c3695c0c18f70709a6c535682a67'
test_expect_success \
'make sure index-pack detects the SHA1 collision' \
'test_must_fail git index-pack -o bad.idx test-3.pack 2>msg &&
grep "SHA1 COLLISION FOUND" msg'
test_done

View File

@@ -31,7 +31,7 @@ test_expect_success 'setup' '
echo "data 5" &&
echo ">2gb" &&
cat commit) |
git fast-import &&
git fast-import --big-file-threshold=2 &&
test ! -f exit-status
'

View File

@@ -434,56 +434,4 @@ test_expect_success 'grep -Fi' '
test_cmp expected actual
'
test_expect_success 'outside of git repository' '
rm -fr non &&
mkdir -p non/git/sub &&
echo hello >non/git/file1 &&
echo world >non/git/sub/file2 &&
echo ".*o*" >non/git/.gitignore &&
{
echo file1:hello &&
echo sub/file2:world
} >non/expect.full &&
echo file2:world >non/expect.sub
(
GIT_CEILING_DIRECTORIES="$(pwd)/non/git" &&
export GIT_CEILING_DIRECTORIES &&
cd non/git &&
test_must_fail git grep o &&
git grep --no-index o >../actual.full &&
test_cmp ../expect.full ../actual.full
cd sub &&
test_must_fail git grep o &&
git grep --no-index o >../../actual.sub &&
test_cmp ../../expect.sub ../../actual.sub
)
'
test_expect_success 'inside git repository but with --no-index' '
rm -fr is &&
mkdir -p is/git/sub &&
echo hello >is/git/file1 &&
echo world >is/git/sub/file2 &&
echo ".*o*" >is/git/.gitignore &&
{
echo file1:hello &&
echo sub/file2:world
} >is/expect.full &&
: >is/expect.empty &&
echo file2:world >is/expect.sub
(
cd is/git &&
git init &&
test_must_fail git grep o >../actual.full &&
test_cmp ../expect.empty ../actual.full &&
git grep --no-index o >../actual.full &&
test_cmp ../expect.full ../actual.full &&
cd sub &&
test_must_fail git grep o >../../actual.sub &&
test_cmp ../../expect.empty ../../actual.sub &&
git grep --no-index o >../../actual.sub &&
test_cmp ../../expect.sub ../../actual.sub
)
'
test_done

View File

@@ -306,4 +306,43 @@ test_expect_success '--remap-to-ancestor with filename filters' '
test $orig_invariant = $(git rev-parse invariant)
'
test_expect_success 'setup submodule' '
rm -fr ?* .git &&
git init &&
test_commit file &&
mkdir submod &&
submodurl="$PWD/submod" &&
( cd submod &&
git init &&
test_commit file-in-submod ) &&
git submodule add "$submodurl" &&
git commit -m "added submodule" &&
test_commit add-file &&
( cd submod && test_commit add-in-submodule ) &&
git add submod &&
git commit -m "changed submodule" &&
git branch original HEAD
'
orig_head=`git show-ref --hash --head HEAD`
test_expect_success 'rewrite submodule with another content' '
git filter-branch --tree-filter "test -d submod && {
rm -rf submod &&
git rm -rf --quiet submod &&
mkdir submod &&
: > submod/file
} || :" HEAD &&
test $orig_head != `git show-ref --hash --head HEAD`
'
test_expect_success 'replace submodule revision' '
git reset --hard original &&
git filter-branch -f --tree-filter \
"if git ls-files --error-unmatch -- submod > /dev/null 2>&1
then git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 submod
fi" HEAD &&
test $orig_head != `git show-ref --hash --head HEAD`
'
test_done

View File

@@ -1536,4 +1536,50 @@ test_expect_success 'R: ignore non-git options' '
git fast-import <input
'
##
## R: very large blobs
##
blobsize=$((2*1024*1024 + 53))
test-genrandom bar $blobsize >expect
cat >input <<INPUT_END
commit refs/heads/big-file
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<COMMIT
R - big file
COMMIT
M 644 inline big1
data $blobsize
INPUT_END
cat expect >>input
cat >>input <<INPUT_END
M 644 inline big2
data $blobsize
INPUT_END
cat expect >>input
echo >>input
test_expect_success \
'R: blob bigger than threshold' \
'test_create_repo R &&
git --git-dir=R/.git fast-import --big-file-threshold=1 <input'
test_expect_success \
'R: verify created pack' \
': >verify &&
for p in R/.git/objects/pack/*.pack;
do
git verify-pack -v $p >>verify || exit;
done'
test_expect_success \
'R: verify written objects' \
'git --git-dir=R/.git cat-file blob big-file:big1 >actual &&
test_cmp expect actual &&
a=$(git --git-dir=R/.git rev-parse big-file:big1) &&
b=$(git --git-dir=R/.git rev-parse big-file:big2) &&
test $a = $b'
test_expect_success \
'R: blob appears only once' \
'n=$(grep $a verify | wc -l) &&
test 1 = $n'
test_done

View File

@@ -33,7 +33,6 @@ test_expect_success \
grep "403 - Snapshot format not allowed" gitweb.output &&
gitweb_run "p=.git;a=snapshot;h=HEAD;sf=zip" &&
grep "403 - Unsupported snapshot format" gitweb.output'
test_debug 'cat gitweb.output'
cat >>gitweb_config.perl <<\EOF
@@ -50,7 +49,6 @@ test_expect_success \
grep "403 - Snapshot format not allowed" gitweb.output &&
gitweb_run "p=.git;a=snapshot;h=HEAD;sf=zip" &&
grep "Status: 200 OK" gitweb.output'
test_debug 'cat gitweb.output'
cat >>gitweb_config.perl <<\EOF
@@ -72,7 +70,7 @@ test_expect_success \
'snapshots: tgz explicitly enabled' \
'gitweb_run "p=.git;a=snapshot;h=HEAD;sf=tgz" &&
grep "Status: 200 OK" gitweb.output'
test_debug 'cat gitweb.output'
test_debug 'cat gitweb.headers'
# ----------------------------------------------------------------------
@@ -82,7 +80,7 @@ test_expect_success 'snapshots: good tree-ish id' '
gitweb_run "p=.git;a=snapshot;h=master;sf=tgz" &&
grep "Status: 200 OK" gitweb.output
'
test_debug 'cat gitweb.output'
test_debug 'cat gitweb.headers'
test_expect_success 'snapshots: bad tree-ish id' '
gitweb_run "p=.git;a=snapshot;h=frizzumFrazzum;sf=tgz" &&
@@ -105,7 +103,7 @@ test_expect_success 'snapshots: good object id' '
gitweb_run "p=.git;a=snapshot;h=$ID;sf=tgz" &&
grep "Status: 200 OK" gitweb.output
'
test_debug 'cat gitweb.output'
test_debug 'cat gitweb.headers'
test_expect_success 'snapshots: bad object id' '
gitweb_run "p=.git;a=snapshot;h=abcdef01234;sf=tgz" &&
@@ -114,4 +112,26 @@ test_expect_success 'snapshots: bad object id' '
test_debug 'cat gitweb.output'
# ----------------------------------------------------------------------
# load checking
# always hit the load limit
cat >>gitweb_config.perl <<\EOF
our $maxload = -1;
EOF
test_expect_success 'load checking: load too high (default action)' '
gitweb_run "p=.git" &&
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
cat >>gitweb_config.perl <<\EOF
our $maxload = undef;
EOF
test_done