* [PATCH] Simplify code outputting relative timestamps in git log
From: Nikolai Weibull @ 2006-08-27 14:23 UTC (permalink / raw)
To: git; +Cc: Nikolai Weibull, Nikolai Weibull
From: Nikolai Weibull <now@puritan.pcp.ath.cx>
The code that outputs relative timestamps is repetitive and can be
simplified by using an array to deal with the various cutoffs. This makes
it easier to modify and remove the cutoffs if we in the future desire to do
so.
Signed-off-by: Nikolai Weibull <now@bitwi.se>
---
date.c | 63 +++++++++++++++++++++++++++++++--------------------------------
1 files changed, 31 insertions(+), 32 deletions(-)
diff --git a/date.c b/date.c
index e387dcd..5891fa8 100644
--- a/date.c
+++ b/date.c
@@ -64,6 +64,29 @@ const char *show_date(unsigned long time
static char timebuf[200];
if (relative) {
+ static struct {
+ char name[8];
+ unsigned long cutoff;
+ unsigned long factor;
+ unsigned long term;
+ } cutoffs[] = {
+#define CUTOFF(name, cutoff, factor, ceiling) \
+ { (name), (cutoff) * (factor), (factor), (ceiling) }
+#define MINUTES(minutes) ((minutes) * 60)
+#define HOURS(hours) ((hours) * MINUTES(60))
+#define DAYS(days) ((days) * HOURS(24))
+ CUTOFF("seconds", 90, 1, 0),
+ CUTOFF("minutes", 90, MINUTES(1), 30),
+ CUTOFF("hours", 36, HOURS(1), MINUTES(30)),
+ CUTOFF("days", 14, DAYS(1), HOURS(12)),
+ CUTOFF("weeks", 12, DAYS(7), HOURS(12)),
+ CUTOFF("months", 12, DAYS(30), HOURS(12))
+#undef MINUTES
+#undef DAYS
+#undef HOURS
+#undef CUTOFF
+ };
+ int i;
unsigned long diff;
time_t t = gm_time_t(time, tz);
struct timeval now;
@@ -71,39 +94,15 @@ const char *show_date(unsigned long time
if (now.tv_sec < t)
return "in the future";
diff = now.tv_sec - t;
- if (diff < 90) {
- snprintf(timebuf, sizeof(timebuf), "%lu seconds ago", diff);
- return timebuf;
- }
- /* Turn it into minutes */
- diff = (diff + 30) / 60;
- if (diff < 90) {
- snprintf(timebuf, sizeof(timebuf), "%lu minutes ago", diff);
- return timebuf;
- }
- /* Turn it into hours */
- diff = (diff + 30) / 60;
- if (diff < 36) {
- snprintf(timebuf, sizeof(timebuf), "%lu hours ago", diff);
- return timebuf;
- }
- /* We deal with number of days from here on */
- diff = (diff + 12) / 24;
- if (diff < 14) {
- snprintf(timebuf, sizeof(timebuf), "%lu days ago", diff);
- return timebuf;
- }
- /* Say weeks for the past 10 weeks or so */
- if (diff < 70) {
- snprintf(timebuf, sizeof(timebuf), "%lu weeks ago", (diff + 3) / 7);
- return timebuf;
- }
- /* Say months for the past 12 months or so */
- if (diff < 360) {
- snprintf(timebuf, sizeof(timebuf), "%lu months ago", (diff + 15) / 30);
- return timebuf;
+ for (i = 0; i < ARRAY_SIZE(cutoffs); i++) {
+ if (diff < cutoffs[i].cutoff) {
+ snprintf(timebuf, sizeof(timebuf), "%lu %s ago",
+ (diff + cutoffs[i].term) / cutoffs[i].factor,
+ cutoffs[i].name);
+ return timebuf;
+ }
}
- /* Else fall back on absolute format.. */
+ /* If we went beyond the month cutoff, use absolute format. */
}
tm = time_to_tm(time, tz);
--
1.4.2.GIT-dirty
^ permalink raw reply related
* Re: File archiver using git
From: Grzegorz Kulewski @ 2006-08-27 13:31 UTC (permalink / raw)
To: Matt McCutchen; +Cc: git
In-Reply-To: <3bbc18d20608270610o102968d2kd340d40843262dc5@mail.gmail.com>
On Sun, 27 Aug 2006, Matt McCutchen wrote:
> Dear git people,
>
> You might like the two attached scripts that I wrote around git to
> pack file trees containing lots of redundancy into very small
> packages. For example, if I have ten slightly different versions of a
> piece of software because I didn't use version control, I can use
> gitar to compress them together.
Does it (and GIT in general) work ok with file permisions, ownership, soft
and hard links, named sockets, device files and similar "strange"
filesystem objects? Do I need any options to GIT to make it work with
them?
Can I for example securely backup or even version-control /etc directory?
Grzegorz Kulewski
^ permalink raw reply
* File archiver using git
From: Matt McCutchen @ 2006-08-27 13:10 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 323 bytes --]
Dear git people,
You might like the two attached scripts that I wrote around git to
pack file trees containing lots of redundancy into very small
packages. For example, if I have ten slightly different versions of a
piece of software because I didn't use version control, I can use
gitar to compress them together.
Matt
[-- Attachment #2: gitar --]
[-- Type: application/octet-stream, Size: 1683 bytes --]
#!/bin/bash
# usage: gitar foo-dir >foo.gitar
set -e
trap 'echo "Unexpected error!
I am leaving the .git subdirectory around so you can troubleshoot;
delete the subdirectory before trying to gitar again." 1>&2' ERR
cd "$1"
if [ -e '.git' ]; then
echo 'The source directory is already a git repository!' 1>&2
exit 1
fi
if ! find . -type d -empty | cmp /dev/null - >/dev/null; then
echo 'WARNING: The source directory contains empty directories, and git will drop them.' 1>&2
fi
# Make repository.
git-init-db >/dev/null
# Make a dummy commit to hold all the files.
function list-files-to-add {
find . -wholename './.git' -prune -or '(' -type f -or -type l ')' -printf '%P\n'
}
list-files-to-add | git-update-index --add --stdin >/dev/null
tree=$(git-write-tree)
function clean-commit {
GIT_AUTHOR_NAME='reproducible' GIT_AUTHOR_EMAIL='' GIT_AUTHOR_DATE='946684801 +0000' GIT_COMMITTER_NAME='reproducible' GIT_COMMITTER_EMAIL='' GIT_COMMITTER_DATE='946684801 +0000' git-commit-tree "$@" </dev/null
}
clean-commit $tree >.git/refs/heads/master
# Pack things up nicely.
git-repack -a >/dev/null
for i in pack idx; do
mv .git/objects/pack/{pack*.$i,pack.$i}
done
git-prune >/dev/null
# Write out git repository as a Matt-style file tree.
function write_file {
echo -n "+ ${#2} $2 "
stat --format=$'f %s' -- "$1/$2"
cat -- "$1/$2"
echo
}
echo '{'
echo '+ 4 HEAD f 23'
echo 'ref: refs/heads/master'
echo
echo '+ 4 refs {'
echo '+ 5 heads {'
write_file .git/refs/heads master
echo '}'
echo '}'
echo '+ 7 objects {'
echo '+ 4 pack {'
write_file .git/objects/pack pack.pack
write_file .git/objects/pack pack.idx
echo '}'
echo '}'
echo '}'
rm -rf .git
[-- Attachment #3: ungitar --]
[-- Type: application/octet-stream, Size: 334 bytes --]
#!/bin/bash
# usage: ungitar foo-dir <foo.gitar
set -e
trap "echo 'Unexpected error!' 1>&2" ERR
if ! [ -e "$1" ]; then
mkdir "$1"
fi
cd "$1"
if [ -e '.git' ]; then
echo 'The destination directory is already a git repository!' 1>&2
exit 1
fi
trap "rm -rf .git" EXIT
ftx .git
git-read-tree master
git-checkout-index --all --force
^ permalink raw reply
* Re: [PATCH] git-daemon: more powerful base-path/user-path settings, using formats.
From: Pierre Habouzit @ 2006-08-27 11:40 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v64gexxgl.fsf@assigned-by-dhcp.cox.net>
[-- Attachment #1: Type: text/plain, Size: 574 bytes --]
Le dim 27 août 2006 12:52, Junio C Hamano a écrit :
> About vger potentially throwing things away, I use this script
> (called "taboo.perl") to check my messages before sending them
> out.
that was not it, I was biten (again) by git-send-mail that uses strftime
(localized) to generate rfc822 dates, making them unparseable :|
I've resent the aggregated patch, that should work right now.
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH] full featured formating function of the --{base,user}_path arguments,
From: Pierre Habouzit @ 2006-08-27 11:39 UTC (permalink / raw)
To: git; +Cc: Pierre Habouzit
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
Documentation/git-daemon.txt | 54 +++++++++++
daemon.c | 207 ++++++++++++++++++++++++++++++++++++++----
2 files changed, 240 insertions(+), 21 deletions(-)
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index 0f7d274..796ae7e 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -11,6 +11,8 @@ SYNOPSIS
'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
[--timeout=n] [--init-timeout=n] [--strict-paths]
[--base-path=path] [--user-path | --user-path=path]
+ [--base-path-fmt=pathfmt] [--user-path-fmt=pathfmt]
+ [--default-hostname=hostname]
[--reuseaddr] [--detach] [--pid-file=file] [directory...]
DESCRIPTION
@@ -45,6 +47,10 @@ OPTIONS
'git://example.com/hello.git', `git-daemon` will interpret the path
as '/srv/git/hello.git'.
+--base-path-fmt=pathfmt::
+ Works like --base-path, but uses a format instead. See Path
+ Formats section below.
+
--export-all::
Allow pulling from all directories that look like GIT repositories
(have the 'objects' and 'refs' subdirectories), even if they
@@ -79,9 +85,20 @@ OPTIONS
taken as a request to access `path/foo` repository in
the home directory of user `alice`.
+--user-path-fmt=pathfmt::
+ Allow ~user notation to be used in requests. The path used to look
+ for the git repository is a format string, see Path Formats
+ section below.
+
--verbose::
Log details about the incoming connections and requested files.
+--default-hostname=hostname::
+ Backward compatibility switch: argument is used as a fallback
+ hostname to use with virtual hosting (to fill the `%h` format in
+ path formats) when the client is too old to provide the information
+ in the query (older than 1.4.0 series).
+
--reuseaddr::
Use SO_REUSEADDR when binding the listening socket.
This allows the server to restart without waiting for
@@ -98,10 +115,45 @@ OPTIONS
--strict-paths is specified this will also include subdirectories
of each named directory.
+Path Formats
+------------
+
+%h::
+ requested hostname. That won't work with clients older than 1.4.0
+ that do not pass the hostname in their query, and in that case, the
+ value of --default-hostname (if any) is used.
+
+%p::
+ requested path.
+
+%P::
+ requested path without the first slash when exists (`/`).
+
+%u::
+ requested username (only allowed for --user-path-fmt).
+
+%%::
+ plain `%`.
+
+Examples
+~~~~~~~~
+
+* `--base-path-fmt=/srv/git/%P` emulates `--base-path=/srv/git`
+
+* `--base-path-fmt=/srv/git/%h%p` will look into
+ `/srv/git/git.example.com/foo` if the request goes to
+ git://git.example.com/foo
+
+* `--user-path-fmt=/home/%u/public_git/%P` works mostly like
+ `--user-path=public_git` (the difference is that it assumes that home
+ directories live in `/home/username` instead of using the real `username`
+ home).
+
Author
------
Written by Linus Torvalds <torvalds@osdl.org>, YOSHIFUJI Hideaki
-<yoshfuji@linux-ipv6.org> and the git-list <git@vger.kernel.org>
+<yoshfuji@linux-ipv6.org>, Pierre Habouzit <madcoder@debian.org>,
+and the git-list <git@vger.kernel.org>
Documentation
--------------
diff --git a/daemon.c b/daemon.c
index 012936f..a2fb9b4 100644
--- a/daemon.c
+++ b/daemon.c
@@ -19,6 +19,8 @@ static const char daemon_usage[] =
"git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n"
" [--timeout=n] [--init-timeout=n] [--strict-paths]\n"
" [--base-path=path] [--user-path | --user-path=path]\n"
+" [--base-path-fmt=pathfmt] [--user-path-fmt=pathfmt]\n"
+" [--default-hostname=hostname]\n"
" [--reuseaddr] [--detach] [--pid-file=file] [directory...]";
/* List of acceptable pathname prefixes */
@@ -29,18 +31,27 @@ static int strict_paths;
static int export_all_trees;
/* Take all paths relative to this one if non-NULL */
-static char *base_path;
+static struct {
+ const char *path;
+ int use_as_fmt;
+} base_path;
/* If defined, ~user notation is allowed and the string is inserted
* after ~user/. E.g. a request to git://host/~alice/frotz would
* go to /home/alice/pub_git/frotz with --user-path=pub_git.
*/
-static const char *user_path;
+static struct {
+ const char *path;
+ int use_as_fmt;
+} user_path;
/* Timeout, and initial timeout */
static unsigned int timeout;
static unsigned int init_timeout;
+/* default host used when the client is old and does not provides host= */
+static char *default_host;
+
static void logreport(int priority, const char *err, va_list params)
{
/* We should do a single write so that it is atomic and output
@@ -148,7 +159,107 @@ static int avoid_alias(char *p)
}
}
-static char *path_ok(char *dir)
+static void check_path_fmt(const char *check, int allow_user)
+{
+ const char *p = check;
+
+ while (*p) {
+ if (*p++ != '%')
+ continue;
+
+ switch (*p) {
+ case '\0':
+ die("invalid format: <%s> ends with an unescaped %%",
+ check);
+
+ case '%':
+ case 'p': case 'P':
+ case 'h':
+ break;
+
+ case 'u':
+ if (allow_user)
+ break;
+ /* fallthrough */
+
+ default:
+ die("invalid format: <%s> uses unknown specifier %%%c",
+ check, *p);
+ }
+
+ p++;
+ }
+}
+
+static char *
+git_path_fmt(char rpath[PATH_MAX], const char *fmt,
+ const char *vhost, const char *path,
+ const char *username, int namlen)
+{
+ const char *p = fmt;
+ int pos = 0;
+
+ while (*p && pos < PATH_MAX) {
+ if (*p != '%') {
+ rpath[pos++] = *p++;
+ continue;
+ }
+
+ switch (*++p) {
+ case '%':
+ rpath[pos++] = *p;
+ break;
+
+ case 'h':
+ if (!vhost && !default_host) {
+ logerror("abort: missing host=, no --default-host given, client is too old");
+ return NULL;
+ }
+
+ if (!vhost) {
+ logerror("old client without host=, using <%s>", default_host);
+ pos += strlcpy(rpath + pos, default_host, PATH_MAX - pos);
+ } else {
+ pos += strlcpy(rpath + pos, vhost, PATH_MAX - pos);
+ }
+ break;
+
+ case 'P':
+ pos += strlcpy(rpath + pos, path + (*path == '/'),
+ PATH_MAX - pos);
+ break;
+
+ case 'p':
+ pos += strlcpy(rpath + pos, path, PATH_MAX - pos);
+ break;
+
+ case 'u':
+ pos += snprintf(rpath + pos, PATH_MAX - pos, "%.*s",
+ namlen, username);
+ break;
+ }
+
+ p++;
+ }
+
+ if (pos >= PATH_MAX) {
+ logerror("generated path is too long");
+ return NULL;
+ }
+
+ rpath[pos] = '\0';
+
+ return rpath;
+}
+
+static inline char *
+git_base_path_fmt(char rpath[PATH_MAX], const char *fmt,
+ const char *vhost, const char *path)
+{
+ return git_path_fmt(rpath, fmt, vhost, path, NULL, 0);
+}
+
+static char *path_ok(char *dir, char *vhost)
{
static char rpath[PATH_MAX];
char *path;
@@ -159,11 +270,11 @@ static char *path_ok(char *dir)
}
if (*dir == '~') {
- if (!user_path) {
+ if (!user_path.path) {
logerror("'%s': User-path not allowed", dir);
return NULL;
}
- if (*user_path) {
+ if (*user_path.path) {
/* Got either "~alice" or "~alice/foo";
* rewrite them to "~alice/%s" or
* "~alice/%s/foo".
@@ -174,24 +285,45 @@ static char *path_ok(char *dir)
slash = dir + restlen;
namlen = slash - dir;
restlen -= namlen;
- loginfo("userpath <%s>, request <%s>, namlen %d, restlen %d, slash <%s>", user_path, dir, namlen, restlen, slash);
- snprintf(rpath, PATH_MAX, "%.*s/%s%.*s",
- namlen, dir, user_path, restlen, slash);
- dir = rpath;
+
+ if (user_path.use_as_fmt) {
+ loginfo("host <%s>, "
+ "userpathfmt <%s>, request <%s>, "
+ "namlen %d, restlen %d, slash <%s>",
+ vhost,
+ user_path.path, dir,
+ namlen, restlen, slash);
+ dir = git_path_fmt(rpath, user_path.path, vhost,
+ slash, dir + 1, namlen - 1);
+ } else {
+ loginfo("userpath <%s>, request <%s>, "
+ "namlen %d, restlen %d, slash <%s>",
+ user_path.path, dir,
+ namlen, restlen, slash);
+ snprintf(rpath, PATH_MAX, "%.*s/%s%.*s",
+ namlen, dir, user_path.path, restlen, slash);
+ dir = rpath;
+ }
}
}
- else if (base_path) {
+ else if (base_path.path) {
if (*dir != '/') {
/* Allow only absolute */
logerror("'%s': Non-absolute path denied (base-path active)", dir);
return NULL;
}
- else {
- snprintf(rpath, PATH_MAX, "%s%s", base_path, dir);
+
+ if (base_path.use_as_fmt) {
+ dir = git_base_path_fmt(rpath, base_path.path, vhost, dir);
+ } else {
+ snprintf(rpath, PATH_MAX, "%s%s", base_path.path, dir);
dir = rpath;
}
}
+ if (!dir)
+ return NULL;
+
path = enter_repo(dir, strict_paths);
if (!path) {
@@ -229,7 +361,7 @@ static char *path_ok(char *dir)
return NULL; /* Fallthrough. Deny by default */
}
-static int upload(char *dir)
+static int upload(char *dir, char *vhost)
{
/* Timeout as string */
char timeout_buf[64];
@@ -237,7 +369,7 @@ static int upload(char *dir)
loginfo("Request for '%s'", dir);
- if (!(path = path_ok(dir)))
+ if (!(path = path_ok(dir, vhost)))
return -1;
/*
@@ -274,6 +406,7 @@ static int execute(struct sockaddr *addr
{
static char line[1000];
int pktlen, len;
+ char *vhost = NULL;
if (addr) {
char addrbuf[256] = "";
@@ -303,15 +436,30 @@ #endif
alarm(0);
len = strlen(line);
- if (pktlen != len)
+
+ if (pktlen != len) {
+ int arg_pos = len + 1;
+
loginfo("Extended attributes (%d bytes) exist <%.*s>",
(int) pktlen - len,
- (int) pktlen - len, line + len + 1);
+ (int) pktlen - len, line + arg_pos);
+
+ while (arg_pos < pktlen) {
+ int arg_len = strlen(line + arg_pos);
+
+ if (!strncmp("host=", line + arg_pos, 5)) {
+ vhost = line + arg_pos + 5;
+ }
+
+ arg_pos += arg_len + 1;
+ }
+ }
+
if (len && line[len-1] == '\n')
line[--len] = 0;
if (!strncmp("git-upload-pack ", line, 16))
- return upload(line+16);
+ return upload(line+16, vhost);
logerror("Protocol error: '%s'", line);
return -1;
@@ -767,19 +915,38 @@ int main(int argc, char **argv)
continue;
}
if (!strncmp(arg, "--base-path=", 12)) {
- base_path = arg+12;
+ base_path.path = arg+12;
+ base_path.use_as_fmt = 0;
+ continue;
+ }
+ if (!strncmp(arg, "--base-path-fmt=", 16)) {
+ base_path.path = arg+16;
+ base_path.use_as_fmt = 1;
+ check_path_fmt(base_path.path, 0);
continue;
}
if (!strcmp(arg, "--reuseaddr")) {
reuseaddr = 1;
continue;
}
+ if (!strncmp(arg, "--default-hostname=", 19)) {
+ default_host = arg + 19;
+ continue;
+ }
if (!strcmp(arg, "--user-path")) {
- user_path = "";
+ user_path.path = "";
+ user_path.use_as_fmt = 0;
continue;
}
if (!strncmp(arg, "--user-path=", 12)) {
- user_path = arg + 12;
+ user_path.path = arg + 12;
+ user_path.use_as_fmt = 0;
+ continue;
+ }
+ if (!strncmp(arg, "--user-path-fmt=", 16)) {
+ user_path.path = arg + 16;
+ user_path.use_as_fmt = 1;
+ check_path_fmt(user_path.path, 1);
continue;
}
if (!strncmp(arg, "--pid-file=", 11)) {
--
1.4.1.1
^ permalink raw reply related
* [PATCH] Add git-zip-tree to .gitignore
From: Rene Scharfe @ 2006-08-27 11:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
diff --git a/.gitignore b/.gitignore
index 55cd984..58a7c92 100644
--- a/.gitignore
+++ b/.gitignore
@@ -124,6 +124,7 @@ git-verify-pack
git-verify-tag
git-whatchanged
git-write-tree
+git-zip-tree
git-core-*/?*
gitweb/gitweb.cgi
test-date
^ permalink raw reply related
* [PATCH] git-reset: remove unused variable
From: Rene Scharfe @ 2006-08-27 11:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
diff --git a/git-reset.sh b/git-reset.sh
index 36fc8ce..3133b5b 100755
--- a/git-reset.sh
+++ b/git-reset.sh
@@ -3,9 +3,6 @@ #!/bin/sh
USAGE='[--mixed | --soft | --hard] [<commit-ish>]'
. git-sh-setup
-tmp=${GIT_DIR}/reset.$$
-trap 'rm -f $tmp-*' 0 1 2 3 15
-
update=
reset_type=--mixed
case "$1" in
^ permalink raw reply related
* [PATCH] git-cherry: remove unused variable
From: Rene Scharfe @ 2006-08-27 11:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
diff --git a/git-cherry.sh b/git-cherry.sh
index f0e8831..8832573 100755
--- a/git-cherry.sh
+++ b/git-cherry.sh
@@ -51,9 +51,6 @@ patch=$tmp-patch
mkdir $patch
trap "rm -rf $tmp-*" 0 1 2 3 15
-_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
-_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
-
for c in $inup
do
git-diff-tree -p $c
^ permalink raw reply related
* Re: [PATCH] git-daemon: more powerful base-path/user-path settings, using formats.
From: Junio C Hamano @ 2006-08-27 10:52 UTC (permalink / raw)
To: Pierre Habouzit; +Cc: git
In-Reply-To: <200608271228.09718.madcoder@debian.org>
Pierre Habouzit <madcoder@debian.org> writes:
> There is also a second patch that never made it to the list that fixes:
> * some indentation problems due to a bad vimrc
> * --default-hostname switch (to handle virtual hosts even with older
> clients)
> * possible overflow in the formatting method.
>
> I'll recompute a new patch that superseeds that one, and merge your
> comments and my never sent patch too.
I have to admit that I kinda liked JDL's simpler one first (and
it has been in production use for some time). We'll see.
About vger potentially throwing things away, I use this script
(called "taboo.perl") to check my messages before sending them
out.
Obviously the taboo-word list itself is not attached here, but
the actual script should have a copy of it after the __DATA__
marker.
-- >8 --
#!/usr/bin/perl -w
my $tmpl = ' if (%%PATTERN%%) {
print "$lineno ${_}matches %%QPATTERN%%\n";
return;
}
';
my $stmt = "";
my $in_header = 1;
while (<DATA>) {
if (/^\$global_taboo_body =/) {
$in_header = 0;
}
next if (/^\043/ || /^\$/ || /^END$/ || /^\s*$/);
chomp;
my $p = $_;
if ($in_header) {
$p = '/^[-\w_]*:/ && ' . $p;
}
my $q = quotemeta($p);
my $stmt1 = $tmpl;
$stmt1 =~ s|%%PATTERN%%|$p|g;
$stmt1 =~ s|%%QPATTERN%%|$q|g;
$stmt .= $stmt1;
}
close DATA;
$stmt = 'sub check {
my ($line, $lineno) = @_;
' . $stmt . '
}
';
eval $stmt;
while (<>) {
check($_, $.);
}
my $how_to_update_this_script = <<'EOF' ;
( sed -e '/^__DATA__$$/q' taboo.perl && \
wget -q -O - http://vger.kernel.org/majordomo-taboos.txt ) \
>taboo.perl+
if diff -u taboo.perl taboo.perl+; \
then \
rm -f taboo.perl+; \
echo >&2 No changes.; \
else \
mv taboo.perl+ taboo.perl; \
chmod +x taboo.perl; \
fi
EOF
__DATA__
^ permalink raw reply
* Re: [PATCH] git-daemon: more powerful base-path/user-path settings, using formats.
From: Pierre Habouzit @ 2006-08-27 10:28 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vfyfiyaex.fsf@assigned-by-dhcp.cox.net>
[-- Attachment #1: Type: text/plain, Size: 1586 bytes --]
Le dim 27 août 2006 08:12, Junio C Hamano a écrit :
> Pierre Habouzit <madcoder@debian.org> writes:
> > Allow a form of virtualhosting, when %h format is used.
> >
> > Signed-off-by: Pierre Habouzit <madcoder@debian.org>
> > ---
> >
> > This is intended to be a more flexible solution, that also
> > gives virtual hosting as a bonus.
>
> Nicely done, almost.
>
> Having to have the distinction between %p and %P formats feels
> somewhat unwieldy, though. Not that I have a better suggestion.
>
> > +int is_base_path_fmt;
> > +int is_user_path_fmt;
>
> I prefer these to be of type "static int".
omg, how did I missed that.
> Although I am not an authority of variable naming, these sound
> funny to me. "is_XXX()" as a function name feels natural,
> "is_XXX" as a variable name does not --- it is not clear what
> the predicate is talking about.
>
> Maybe "use_fmt_for_base_path" is easier to understand? I dunno.
> Or "user_path_is_fmt"? That's more logical but still somewhat
> feels funny.
agreed.
There is also a second patch that never made it to the list that fixes:
* some indentation problems due to a bad vimrc
* --default-hostname switch (to handle virtual hosts even with older
clients)
* possible overflow in the formatting method.
I'll recompute a new patch that superseeds that one, and merge your
comments and my never sent patch too.
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH] git-daemon: more powerful base-path/user-path settings, using formats.
From: Junio C Hamano @ 2006-08-27 6:12 UTC (permalink / raw)
To: Pierre Habouzit; +Cc: git
In-Reply-To: <115637597423-git-send-email-madcoder@debian.org>
Pierre Habouzit <madcoder@debian.org> writes:
> Allow a form of virtualhosting, when %h format is used.
>
> Signed-off-by: Pierre Habouzit <madcoder@debian.org>
> ---
>
> This is intended to be a more flexible solution, that also gives virtual
> hosting as a bonus.
Nicely done, almost.
Having to have the distinction between %p and %P formats feels
somewhat unwieldy, though. Not that I have a better suggestion.
> +int is_base_path_fmt;
> +int is_user_path_fmt;
I prefer these to be of type "static int".
Although I am not an authority of variable naming, these sound
funny to me. "is_XXX()" as a function name feels natural,
"is_XXX" as a variable name does not --- it is not clear what
the predicate is talking about.
Maybe "use_fmt_for_base_path" is easier to understand? I dunno.
Or "user_path_is_fmt"? That's more logical but still somewhat
feels funny.
^ permalink raw reply
* Re: [PATCH] Refactoring tracing code in "git.c" and "exec_cmd.c".
From: Junio C Hamano @ 2006-08-27 5:42 UTC (permalink / raw)
To: Christian Couder; +Cc: git
In-Reply-To: <20060824074547.a8fa0005.chriscool@tuxfamily.org>
Christian Couder <chriscool@tuxfamily.org> writes:
> Some new helper functions in "quote.c" are used for this.
> The goal is also to get near the point where we can use
> one write(2) call to trace in any open file descriptor.
> This is why we put the trace string into one buffer.
>
> Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
I really liked the fact (not necessarily the way, though) this
shortens the callers.
> diff --git a/quote.c b/quote.c
> index e220dcc..84d0b7b 100644
> --- a/quote.c
> +++ b/quote.c
> @@ -74,6 +74,84 @@ char *sq_quote(const char *src)
> return buf;
> }
>
> +char *sq_quote_argv(const char** argv, int count)
> +{
> + char *buf, *to;
> + int i;
> + size_t len;
> +
> + /* Count argv if needed. */
> + if (count < 0) {
> + char **p = (char **)argv;
> + count = 0;
> + while (*p++) count++;
> + }
Wouldn't this be easier to read?
if (count < 0)
for (count = 0; argv[count]; count++)
; /* just counting */
> + /* Get destination buffer length. */
> + len = count ? count : 1;
This confused me quite a bit. Wouldn't it be simpler to special
case the count==0 case and return xcalloc(1,1) here (this would
allow you to lose "if (!count)" later as well)?
> + /* Copy into destination buffer. */
> + for (i = 0; i < count; ++i) {
> + if (i) *to++ = ' ';
(style)
if (i)
*to++ = ' ';
> + to += sq_quote_buf(to, len, argv[i]);
> + }
> +
> + if (!count)
> + *buf = 0;
> +
> + return buf;
> +}
> +/* Return a newly allocated copy of "format" where the
> + * first occurence of "old" has been replaced by "new". */
> +static char *str_subst(const char *format, const char *old, const char *new)
> +{
I do not think there is anything wrong with this function
per-se, but...
> +void sq_quote_argv_printf(FILE* out, const char **argv, int count,
> + const char *format, ...)
> +{
> + /* Replace the string "ARGV" in format with the quoted arg values. */
> + char *argv_str = sq_quote_argv(argv, count);
> + char *new_format = str_subst(format, "ARGV", argv_str);
> +
> + /* Print into "out" using the new format. */
> + va_list rest;
> + va_start(rest, format);
> + vfprintf(out, new_format, rest);
> + va_end(rest);
this feels wrong. What happens when the original argv had
a per-cent in it?
^ permalink raw reply
* Re: [PATCH 00/19] gitweb: Remove dependency on external diff and need for temporary files
From: Linus Torvalds @ 2006-08-27 3:54 UTC (permalink / raw)
To: David Miller; +Cc: jnareb, git
In-Reply-To: <20060826.204208.85688529.davem@davemloft.net>
On Sat, 26 Aug 2006, David Miller wrote:
>
> > Ok, can we now please fix my final annouyance, which is that gitweb from
> > the very beginning has apparently believed that the "Signed-off-by:" etc
> > lines are not important, and they get stripped away when looking at the
> > "commit-diff".
>
> Isn't this to keep the email address from being published on the web
> and thus harvested by spammers?
Well, since gitweb already exposes all of those in the "commit" thing (in
a different color, but they are there), I don't see why "commit-diff"
wouldn't show the same data..
I would certainly _hope_ that every developer has a spam blocker. I don't
think not showing email addresses is the answer to _that_ particular
problem (and if somebody wants to harvest the email addresses for a git
project that is exposed with gitweb, there are more efficient ways to do
that ;)
Linus
^ permalink raw reply
* Re: [PATCH 00/19] gitweb: Remove dependency on external diff and need for temporary files
From: David Miller @ 2006-08-27 3:42 UTC (permalink / raw)
To: torvalds; +Cc: jnareb, git
In-Reply-To: <Pine.LNX.4.64.0608262026230.11811@g5.osdl.org>
From: Linus Torvalds <torvalds@osdl.org>
Date: Sat, 26 Aug 2006 20:30:49 -0700 (PDT)
> Ok, can we now please fix my final annouyance, which is that gitweb from
> the very beginning has apparently believed that the "Signed-off-by:" etc
> lines are not important, and they get stripped away when looking at the
> "commit-diff".
Isn't this to keep the email address from being published on the web
and thus harvested by spammers?
If it will obfuscate the email address, that's fine I guess.
^ permalink raw reply
* Re: [PATCH 13/19] gitweb: Add invisible hyperlink to from-file/to-file diff header
From: Linus Torvalds @ 2006-08-27 3:38 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <200608252105.07500.jnareb@gmail.com>
On Fri, 25 Aug 2006, Jakub Narebski wrote:
>
> Change replacing hashes as from-file/to-file with filenames from
> difftree to adding invisible (except underlining on hover/mouseover)
> hyperlink to from-file/to-file blob. /dev/null as from-file or
> to-file is not changed (is not hyperlinked).
Wouldn't it be even better to have the hyperlink (or a new, separate one)
point to the history for that file, too?
That way, you can go to the commit-diff, and when you see a diff for a
file, you can easily just ask for the whole history for that file. As it
is, you can get that, but only by going to the "commit" thing, not from
the "commit-diff" thing.
Alternatively, maybe commit-diff should have a header with the files it
changes (ie it would truly be a superset of the "commit" case)? That might
be even nicer, since you'd not have to scroll through a potentially big
diff for other files in order to get to the one you care about.
(If you do the "header with changed files", each file could have the same
three buttons as in the "commit" view: "blob" (pointing to the blob),
"diff" (which just points to _within_ the current window, so that you can
get to the start of that particular file diff) and "history" (which
obviously does what the "commit" case does too - generate a history page).
Linus
^ permalink raw reply
* Re: [PATCH 00/19] gitweb: Remove dependency on external diff and need for temporary files
From: Linus Torvalds @ 2006-08-27 3:30 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <200608252315.57181.jnareb@gmail.com>
On Fri, 25 Aug 2006, Jakub Narebski wrote:
>
> This series of patches (now finished) removes dependency on
> external diff (/usr/bin/diff) to produce commitdiff and blobdiff
> views, and the need for temporary files.
Ok, can we now please fix my final annouyance, which is that gitweb from
the very beginning has apparently believed that the "Signed-off-by:" etc
lines are not important, and they get stripped away when looking at the
"commit-diff".
Also, "commit-diff" really should have some minimal authorship
information. It's silly to have to go to "commit" and then separately ask
for "diff" to see all these very basic things.
So I think that "commit-diff" should basically show the equivalent of "git
show --pretty", ie author, date, commit message (including sign-offs) and
then the diff.
No?
Linus
^ permalink raw reply
* Re: [PATCH] dir: do all size checks before seeking back and fix file closing
From: Junio C Hamano @ 2006-08-27 3:04 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
In-Reply-To: <Pine.LNX.4.64.0608261931460.11811@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
>> The comparison order is done in textual order. You list smaller
>> things on the left and then larger things on the right (iow, you
>> almost never use >= or >).
>
> Ahh. A number of people do the "0 == x" thing, because they want to be
> caught if they use "=" instead of "==" by mistake. I thought it was the
> same thing.
The rest is repeating what you said 15 months ago, so I did not
quote that part, but interested parties can follow this thread:
http://thread.gmane.org/gmane.comp.version-control.git/3907/focus=4126
^ permalink raw reply
* Re: [PATCH 19/19] gitweb: Remove creating directory for temporary files
From: Junio C Hamano @ 2006-08-27 2:51 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <ecqaa3$j0u$1@sea.gmane.org>
Jakub Narebski <jnareb@gmail.com> writes:
> Junio C Hamano wrote:
>
>> Jakub Narebski <jnareb@gmail.com> writes:
>>
>> * 13/19 gitweb: Add invisible hyperlink to from-file/to-file diff header
>>
>> You seem to have forgotten esc_html() on the patch-line
>> before sending it to the browser. Careful.
>
> Cannot esc_html() line with HTML code, namely the hyperlink.
OK, I did not notice the lines are already HTMLified with links
at that point.
>> * 14/19 gitweb: Always display link to blobdiff_plain in git_blobdiff
>>
>> Need justification why this change is needed (or why previous
>> logic to avoid showing it in certain cases is wrong).
>
> Why we didn't display it before? I though it was a bug (oversimplification
> in case we don't have $hash_base or it is not a commit). If we can display
> "blob" view, we can display "blob_plain" view...
I take it that you mean that it avoids the case without
$hash_base even though it can do all the necessary computation
without it. If so please say that in the commit log message.
>> You seem to spell out '-M', '-C' everywhere. I suspect
>> fixing them all to just '-C' (or perhaps '-B', '-C') would be
>> tedious but probably is a good idea.
>
> Does '-C' imply '-M'?
They are, in this order "-M" < "-C" < "--find-copies-harder -C",
strict superset/subset of each other.
Having said that, I think just -M (or perhaps -B -M) might be a
better default (or "only choice" if the UI does not give a
choice), for a few reasons:
* -C tends to be far more expensive than -M. The cost of -M is
proportional to (number of removed files) * (number of new
files). The cost of -C is proportional to (number of
changed files + number of removed files) * (number of new
files). For -C with --find-copies-harder, the cost is still
more expensive: (number of files in the original tree) *
(number of new files).
* -C does not detect all copies. It considers only the
pre-image of files changed in the same commit as candidates
of copy source. To make it consider _any_ file that was in
the original tree, you would need to give --find-copies-harder
as well. In a way, -C is a cheaper (but still more
expensive) compromise, middle ground between -M and -C
--find-copies-harder.
>> * 17/19 gitweb: git_blobdiff_plain is git_blobdiff('plain')
>>
>> Needs justification why commitdiff and blobdiff plain needs
>> to behave differently.
>
> First, if we have blobdiff generated with renames/copying detection (and
> "commit" view uses it, and provides link to blobdiffs using it), there not
> always is single diff (blobdiff) without renames/copying detection. So to
> have blobdiff and blobdiff_plain equivalent, and blobdiff_plain without
> renames detection, then blobdiff_plain view would have sometimes _two_
> patches.
Sorry, does not parse, but two paragraphs below I think you made
it clear why.
> The idea behind changing comittdiff (HTML version) to including rename
> detection was that it gives shorter and better to understand patches. The
> idea (perhaps wrong) behind leaving comitdiff_plain output without renames
> detection was that this output can be applied directly by non-git-aware
> tools. It can be easily changed to include renames/copying detection (put
> '-C' in one place).
>
> The idea behind having both blobdiff and blobdiff_plain have renames
> detection was that commit view used rename detection, the two views should
> be equivalent and one exist always for the other, and that it was easier on
> implementation ;-)
I am not sure about this. People, especially the ones who do
_not_ use git and are interested in one single fix, are the ones
you are trying to help, because they can just be told about the
change (e.g. "'Fix bar blah' patch in Linus tree last week might
fix your problems"), go to gitweb and use it. But:
(0) If rename/copy is not involved there is no difference so I
will not discuss that case further;
(1) If rename/copy is involved, as you say, the patch is far
easier to understand in git form; the person who downloaded
the patch would have a hard time understanding it before
applying the patch if you do not do -M/-C.
(2) The post-image file would not exist in the tree the person
who downloaded the patch has for renamed/copied paths, so
failure from "patch -p1" is immediately noticeable. The
metainformation says what was renamed/copied where, and I
do not think it is too much to expect for them to first
rename/copy by hand then re-run "patch -p1".
(3) If we do not do -M, in situations where the patch has fuzz
or conflict when applied to the tree the person who
downloaded has, the post-image patch will be applied
cleanly and the removal patch will have conflict or fuzz.
The local change can easily be lost that way.
> P.S. I have most problems with having legacy blobdiff URL (without 'hpb'
> i.e. hash_parent_base parameter) working correctly without making use of
> external diff.
Are people bookmarking such URLs? How important is the legacy
compatibility?
^ permalink raw reply
* Re: [PATCH] dir: do all size checks before seeking back and fix file closing
From: Linus Torvalds @ 2006-08-27 2:37 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v4pvz11o6.fsf@assigned-by-dhcp.cox.net>
On Sat, 26 Aug 2006, Junio C Hamano wrote:
>
> > Now, admittedly it's wrong because another bad habit Junio picked up
> > (doing comparisons with constants in the wrong order)
>
> I think you misunderstand the rationale used to encourage the
> comparison used there. It does not have anything to do with
> having comparison on the left.
>
> The comparison order is done in textual order. You list smaller
> things on the left and then larger things on the right (iow, you
> almost never use >= or >).
Ahh. A number of people do the "0 == x" thing, because they want to be
caught if they use "=" instead of "==" by mistake. I thought it was the
same thing.
> This does not come from any authoritative source, but I picked
> it up because I felt it made a lot of sense.
To anybody who has _ever_ done any math at all, it makes no sense at all.
You _always_ put constants on the right-hand side (or, possibly last on
the left-hand side, in order to make the right-hand side be "0").
Similarly, if you say it out loud, you'd always say "if 'x' is larger than
or equal to zero", not "if zero is smaller or less than 'x'". That's
because "zero" obviously never varies, so you'd never talk about "zero"
being compared to anything else.
The only exception would be the mathematical "0 < x < 10" kind of thing,
which some languages (not C, of course) allows in that form. I can imagine
that people would just do that as "0 < x && x < 10" just to keep the C
form as close to the mathematical form, although I would at least
personally do it as
if (x > 0 &&
x < 10)
especially if I ever needed to write it that way on multiple lines due to
some of the expressions being more complicated.
Linus
^ permalink raw reply
* Re: [PATCH] dir: do all size checks before seeking back and fix file closing
From: Junio C Hamano @ 2006-08-27 2:15 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <7v4pvz11o6.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
> Linus Torvalds <torvalds@osdl.org> writes:
>
>> Now, admittedly it's wrong because another bad habit Junio picked up
>> (doing comparisons with constants in the wrong order)
>
> I think you misunderstand the rationale used to encourage the
> comparison used there. It does not have anything to do with
> having comparison on the left.
s/comparison/constant/; I cannot spell.
^ permalink raw reply
* Re: Relative timestamps in git log
From: Junio C Hamano @ 2006-08-27 1:22 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0608261537120.11811@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> The exact cut-off points when it switches from days to weeks etc are
> totally arbitrary, but are picked somewhat to avoid the "1 weeks ago"
> thing (by making it show "10 days ago" rather than "1 week", or "70
> minutes ago" rather than "1 hour ago").
It might be arbitrary but I agree they make sense.
The code was quite confusing in that after you turn it into days
you stop converting to larger scale and I was going to nitpick
that 365 weeks do not make much sense. I think you meant to do
a "Turn it into weeks" conversion before comparing diff with 53
and then changed your mind, got confused yourself that diff is
still in days and decided to say "months" for the past year.
IOW, I think there is a bug around weeks/months code ;-). On
top of your patch how about the attached?
Personally I have mixed feeling about "months" scale. On one
hand, I think it could extend to 30 months or so without losing
readability when one is interested in "how long ago did this
happen". On the other hand, it would take more time for me if I
see "this happened 5 months ago" than "this happened in March
this year" to recollect what the context of the particular
change was ("ah I needed that feature when I was preparing the
committer/author graph for OLS paper deadline").
P.S. welcome back to the list.
diff --git a/date.c b/date.c
index 92e3f6e..914fd82 100644
--- a/date.c
+++ b/date.c
@@ -87,17 +87,19 @@ const char *show_date(unsigned long time
snprintf(timebuf, sizeof(timebuf), "%lu hours ago", diff);
return timebuf;
}
- /* Turn it into days */
+ /* Turn it into days; from here on we deal with days */
diff = (diff + 12) / 24;
if (diff < 14) {
snprintf(timebuf, sizeof(timebuf), "%lu days ago", diff);
return timebuf;
}
- if (diff < 53) {
+ /* Say weeks for the past 6 months or so */
+ if (diff < 180) {
snprintf(timebuf, sizeof(timebuf), "%lu weeks ago", (diff + 3) / 7);
return timebuf;
}
- if (diff < 365) {
+ /* Say months for the past 30 months or so */
+ if (diff < 912) {
snprintf(timebuf, sizeof(timebuf), "%lu months ago", (diff + 15) / 30);
return timebuf;
}
^ permalink raw reply related
* Re: [PATCH 19/19] gitweb: Remove creating directory for temporary files
From: Jakub Narebski @ 2006-08-27 0:38 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vwt8vyqij.fsf@assigned-by-dhcp.cox.net>
On 8/27/06, Junio C Hamano <junkio@cox.net> wrote:
> Junio C Hamano <junkio@cox.net> writes:
>
>> "get-following" is inherently a very expensive operation, so
>> I would suggest not doing this. It seems that nobody uses
>> these two subs yet, so probably it is better to yank them
>> before they cause damages.
>
> A bit of clarification. gitk has preceding/following but unlike
> gitweb it has three things that go in favor of having it.
>
> - gitk can afford to use as much CPU as the user throw at it,
> since it runs locally.
>
> - gitk finds preceding/following in the background so the user
> does not have to wait, and it is done while it gets the list
> of commits which it needs to do anyway.
I wonder if we could AJAXize gitweb, and have _browser_ compute
preceding/following tags using some JavaScript...
That would be client side, could be in background, and could be cached. :-)
--
Jakub Narebski
ShadeHawk on #git
^ permalink raw reply
* Re: [PATCH 19/19] gitweb: Remove creating directory for temporary files
From: Junio C Hamano @ 2006-08-27 0:24 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <7vpsen1eq3.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
> "get-following" is inherently a very expensive operation, so
> I would suggest not doing this. It seems that nobody uses
> these two subs yet, so probably it is better to yank them
> before they cause damages.
A bit of clarification. gitk has preceding/following but unlike
gitweb it has three things that go in favor of having it.
- gitk can afford to use as much CPU as the user throw at it,
since it runs locally.
- gitk finds preceding/following in the background so the user
does not have to wait, and it is done while it gets the list
of commits which it needs to do anyway.
- what gitk reads from rev-list persists while the user keeps
it around. when the user walks around inspecting different
commits, the cost for computing preceding/following is
amortized. gitweb cannot do this unless it somehow caches
this information, but you just spent significant effort to
make it unnecessary for gitweb to write anything on the
filesystem, so introducing caching is somewhat going
backwards.
^ permalink raw reply
* Re: [PATCH] dir: do all size checks before seeking back and fix file closing
From: Junio C Hamano @ 2006-08-27 0:07 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0608261509290.11811@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> I really think you'd be better off rewriting that to use "fstat()"
> instead. I don't know why it uses two lseek's, but it's wrong, and looks
> like some bad habit Junio picked up at some point.
I think the code was written to avoid getting confused by
unseekable input (pipes) but was done in early morning before
the first shot of caffeine.
> Now, admittedly it's wrong because another bad habit Junio picked up
> (doing comparisons with constants in the wrong order)
I think you misunderstand the rationale used to encourage the
comparison used there. It does not have anything to do with
having comparison on the left.
The comparison order is done in textual order. You list smaller
things on the left and then larger things on the right (iow, you
almost never use >= or >).
> Junio: I realize that you claim that you learnt that syntax from an
> authorative source, but he was _wrong_....
This does not come from any authoritative source, but I picked
it up because I felt it made a lot of sense.
> ... Doing the constant first is more likely to cause bugs,
> rather than less.
That's a funny thing to say, because I was about to send out a
comment that touches this exact topic.
I spotted the bug the patch was trying to introduce right away
_because_ the original comparison was written in textual order.
The patch changed the comparison operator which first confused
me for a handful seconds, and then after I swapped everything in
my head to read as
if (fd <= 0)
close(fd);
it became blatantly obvious it was a bogus change. In the
message I was about to send out, I would have said "a fine
example that using texual order comparison consistently avoids
bugs". So it is really relative to what you are used to.
Get used to it, please ;-).
^ permalink raw reply
* Relative timestamps in git log
From: Linus Torvalds @ 2006-08-26 22:45 UTC (permalink / raw)
To: Junio C Hamano, Git Mailing List
I noticed that I was looking at the kernel gitweb output at some point
rather than just do "git log", simply because I liked seeing the
simplified date-format, ie the "5 days ago" rather than a full date.
This adds infrastructure to do that for "git log" too. It does NOT add the
actual flag to enable it, though, so right now this patch is a no-op, but
it should now be easy to add a command line flag (and possibly a config
file option) to just turn on the "relative" date format.
The exact cut-off points when it switches from days to weeks etc are
totally arbitrary, but are picked somewhat to avoid the "1 weeks ago"
thing (by making it show "10 days ago" rather than "1 week", or "70
minutes ago" rather than "1 hour ago").
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
With this, and changing the ", 0" for CMIT_FMT_MEDIUM into a ", 1", I get
output like:
commit a7f051987c5f020e60da1e5d6ddefc3d443d3299
Merge: 030b520... a8e0d16...
Author: Junio C Hamano <junkio@cox.net>
Date: 22 hours ago
Merge branch 'gl/cleanup'
* gl/cleanup:
Convert memset(hash,0,20) to hashclr(hash).
Convert memcpy(a,b,20) to hashcpy(a,b).
commit 030b52087f0a4b7b1178d34839868ce438eb2f0e
Author: Jakub Narebski <jnareb@gmail.com>
Date: 20 hours ago
gitweb: git_annotate didn't expect negative numeric timezone
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
commit b22d449721b22f6ec090f22c418ae6b0a560f78d
Author: Eric Wong <normalperson@yhbt.net>
Date: 23 hours ago
git-svn: add the 'dcommit' command
This is a high-level wrapper around the 'commit-diff' command
and used to produce cleaner history against the mirrored repository
through rebase/reset usage.
It's basically a more polished version of this:
for i in `git rev-list --no-merges remotes/git-svn..HEAD | tac`; do
git-svn commit-diff $i~1 $i
done
git reset --hard remotes/git-svn
Signed-off-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
which looks quite readable..
diff --git a/builtin-cat-file.c b/builtin-cat-file.c
index 7a6fa56..6c16bfa 100644
--- a/builtin-cat-file.c
+++ b/builtin-cat-file.c
@@ -54,7 +54,7 @@ static void pprint_tag(const unsigned ch
write_or_die(1, tagger, sp - tagger);
date = strtoul(sp, &ep, 10);
tz = strtol(ep, NULL, 10);
- sp = show_date(date, tz);
+ sp = show_date(date, tz, 0);
write_or_die(1, sp, strlen(sp));
xwrite(1, "\n", 1);
break;
diff --git a/cache.h b/cache.h
index 1f212d7..ccb83a1 100644
--- a/cache.h
+++ b/cache.h
@@ -286,7 +286,7 @@ extern void *read_object_with_reference(
unsigned long *size,
unsigned char *sha1_ret);
-const char *show_date(unsigned long time, int timezone);
+const char *show_date(unsigned long time, int timezone, int relative);
const char *show_rfc2822_date(unsigned long time, int timezone);
int parse_date(const char *date, char *buf, int bufsize);
void datestamp(char *buf, int bufsize);
diff --git a/commit.c b/commit.c
index 00bc3de..c3ff9b4 100644
--- a/commit.c
+++ b/commit.c
@@ -507,14 +507,14 @@ static int add_user_info(const char *wha
}
switch (fmt) {
case CMIT_FMT_MEDIUM:
- ret += sprintf(buf + ret, "Date: %s\n", show_date(time, tz));
+ ret += sprintf(buf + ret, "Date: %s\n", show_date(time, tz, 0));
break;
case CMIT_FMT_EMAIL:
ret += sprintf(buf + ret, "Date: %s\n",
show_rfc2822_date(time, tz));
break;
case CMIT_FMT_FULLER:
- ret += sprintf(buf + ret, "%sDate: %s\n", what, show_date(time, tz));
+ ret += sprintf(buf + ret, "%sDate: %s\n", what, show_date(time, tz, 0));
break;
default:
/* notin' */
diff --git a/date.c b/date.c
index d780846..92e3f6e 100644
--- a/date.c
+++ b/date.c
@@ -37,6 +37,16 @@ static const char *weekday_names[] = {
"Sundays", "Mondays", "Tuesdays", "Wednesdays", "Thursdays", "Fridays", "Saturdays"
};
+static time_t gm_time_t(unsigned long time, int tz)
+{
+ int minutes;
+
+ minutes = tz < 0 ? -tz : tz;
+ minutes = (minutes / 100)*60 + (minutes % 100);
+ minutes = tz < 0 ? -minutes : minutes;
+ return time + minutes * 60;
+}
+
/*
* The "tz" thing is passed in as this strange "decimal parse of tz"
* thing, which means that tz -0100 is passed in as the integer -100,
@@ -44,21 +54,56 @@ static const char *weekday_names[] = {
*/
static struct tm *time_to_tm(unsigned long time, int tz)
{
- time_t t;
- int minutes;
-
- minutes = tz < 0 ? -tz : tz;
- minutes = (minutes / 100)*60 + (minutes % 100);
- minutes = tz < 0 ? -minutes : minutes;
- t = time + minutes * 60;
+ time_t t = gm_time_t(time, tz);
return gmtime(&t);
}
-const char *show_date(unsigned long time, int tz)
+const char *show_date(unsigned long time, int tz, int relative)
{
struct tm *tm;
static char timebuf[200];
+ if (relative) {
+ unsigned long diff;
+ time_t t = gm_time_t(time, tz);
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ if (now.tv_sec < t)
+ return "in the future";
+ diff = now.tv_sec - t;
+ if (diff < 90) {
+ snprintf(timebuf, sizeof(timebuf), "%lu seconds ago", diff);
+ return timebuf;
+ }
+ /* Turn it into minutes */
+ diff = (diff + 30) / 60;
+ if (diff < 90) {
+ snprintf(timebuf, sizeof(timebuf), "%lu minutes ago", diff);
+ return timebuf;
+ }
+ /* Turn it into hours */
+ diff = (diff + 30) / 60;
+ if (diff < 36) {
+ snprintf(timebuf, sizeof(timebuf), "%lu hours ago", diff);
+ return timebuf;
+ }
+ /* Turn it into days */
+ diff = (diff + 12) / 24;
+ if (diff < 14) {
+ snprintf(timebuf, sizeof(timebuf), "%lu days ago", diff);
+ return timebuf;
+ }
+ if (diff < 53) {
+ snprintf(timebuf, sizeof(timebuf), "%lu weeks ago", (diff + 3) / 7);
+ return timebuf;
+ }
+ if (diff < 365) {
+ snprintf(timebuf, sizeof(timebuf), "%lu months ago", (diff + 15) / 30);
+ return timebuf;
+ }
+ /* Else fall back on absolute format.. */
+ }
+
tm = time_to_tm(time, tz);
if (!tm)
return NULL;
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox