* Re: Change set based shallow clone
From: A Large Angry SCM @ 2006-09-08 17:18 UTC (permalink / raw)
To: Martin Langhoff; +Cc: Junio C Hamano, Jon Smirl, git
In-Reply-To: <46a038f90609080015u56daae78u9d78584edae7fb72@mail.gmail.com>
Martin Langhoff wrote:
> On 9/8/06, Junio C Hamano <junkio@cox.net> wrote:
...
>> [*4*] In git, there is no inherent server vs client or upstream
>> vs downstream relationship between repositories.
>
> Here an importaant distiction must be made. A "publishing" repo cannot
> be sparse. A sparse repo probably cannot be cloned from.
With the use of "placeholder" objects; neither one of these assertions
is true.
^ permalink raw reply
* Re: Change set based shallow clone
From: linux @ 2006-09-08 18:42 UTC (permalink / raw)
To: jonsmirl, linux; +Cc: git
In-Reply-To: <9e4733910609071923tf1c49f6o70419e961e9eb66f@mail.gmail.com>
Thanks for making suggestions. It's easier to knock straw men down
than make them. But forgive me if I have fun pointing out the holes...
>> Okay. Now, the server hasn't heard of one or more of those commit
>> objects, because they're local changes. What then?
>
> Toss them, if they don't exist on the server the server is going to be
> able to send any objects for them.
Er... that makes "git pull git://git.other-hacker.personal/dir"
impossible. There's a reason that git can handle this as it presently
exists:
a-b-c-d-e-f <-- HEAD
/
Hacker 1: o-o-o-o <-- origin
Hacker 2: o-o-o-o-o-o <-- origin
\
v-w-x-y <-- HEAD
Suppose hacker 2, who happened to sync with upstream more recently,
wants to pull from hacker 1, in the hopes of building
a-b-c-d-e-f
/ \
Hacker 2: o-o-o-o-o-o z <-- HEAD
\ /
v-w-x-y
This works now, and should continue to work.
> Client would track this incrementally and not recompute it each time.
Yes, this is probably possible. I haven't worked it out, but given a
cache of precomputed (commit,depth) numbers, you can trace back from the
new heads until you hit a cache entry.
> If you follow the links in what looks to be a dangling object sooner
> or latter you will run into the root object or a 'not present' object.
> If you hit one of those the objects are not dangling and should be
> preserved.
I don't understand. It seems like you're saying that any commit without an
ancestor, and all objects recursively pointing to it, are not garbage.
How would anything ever get declared garbage in this case?
> Here is another way to look at the shallow clone problem. The only
> public ids in a git tree are the head and tag pointers. Send these to
> the client. Now let's modify the git tools to fault the full objects
> in one by one from the server whenever a git operation needs the
> object. Dangling references would point to 'not-present' objects.
Er... that would fault in a gigabyte the first time someone ran gitk,
or several other history-browsing commands. Don't you need a way to say
"tell the user this isn't present and will take an hour to download"?
Well, thinking, there are actually two shallow clone possibilities:
1) Don't load the unwanted commit objects
2) Clone the commit objects, but not their trees.
The latter would let you browse the commit history, at least.
^ permalink raw reply
* Re: Add git-archive [take #2]
From: Rene Scharfe @ 2006-09-08 20:21 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Franck, git
In-Reply-To: <7v8xkvqjlq.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano schrieb:
> Franck Bui-Huu <vagabon.xyz@gmail.com> writes:
>
>> I'm sending a new version of the patchset which allows
>> 'git-archive' and 'git-upload-archive' command. I tried to take
>> into account all feedbacks made by Junio and Rene, but there are
>> still some open points.
>>
>> 1/ Allow 'git-upload-archive' command to enable/disable some
>> formats. This should be done by 'git-upload-archive'.
>
> Perhaps. I was thinking about the way how a site administrator can
> configure such when upload-archive is spawned via git-daemon (for
> users coming from ssh and spawn an upload-archive on their own, it's
> their own process and upload-archive has no business deciding what is
> allowed and what is forbidden). Not very many clean ways I can
> think of unfortunately.
Mmpf, ssh is (one of the things) in my blind spot. Do you mean a
ssh+git-shell connection? One could argue that since this is a
restricted connection anyway upload-archive _has_ a right to restrict
archive format etc., too. On a full, unrestricted ssh connection one
can start git-archive directly. I'd do that anyway because I'm used to
do this with tar. ;-)
Anyway, I think having config options for git-upload-archive for
restricting formats and compression levels is as clean as we can get in
the absence of a way for upload-archive to detect which protocol is
used for the current connection. Mmh, maybe an environment variable
which is set by the daemon can be used? This is no dirtier than what
webservers do..
René
^ permalink raw reply
* Re: [PATCH 1/4] Add git-archive
From: Rene Scharfe @ 2006-09-08 20:21 UTC (permalink / raw)
To: Franck; +Cc: Junio C Hamano, git
In-Reply-To: <45013114.1070808@innova-card.com>
Only a few trivial comments, as I managed to catch a cold somehow and
can't think straight for longer than three seconds.
> .gitignore | 1
> Documentation/git-archive.txt | 100 ++++++++++++++++++
> Makefile | 3 -
> archive.h | 41 +++++++
> builtin-archive.c | 225 +++++++++++++++++++++++++++++++++++++++++
> builtin.h | 1
> generate-cmdlist.sh | 1
> git.c | 1
> 8 files changed, 372 insertions(+), 1 deletions(-)
>
> diff --git a/.gitignore b/.gitignore
> index 78cb671..a3e7ca1 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -8,6 +8,7 @@ git-apply
> git-applymbox
> git-applypatch
> git-archimport
> +git-archive
> git-bisect
> git-branch
> git-cat-file
> diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
> new file mode 100644
> index 0000000..913528d
> --- /dev/null
> +++ b/Documentation/git-archive.txt
> @@ -0,0 +1,100 @@
> +git-archive(1)
> +==============
> +
> +NAME
> +----
> +git-archive - Creates a archive of the files in the named tree
> +
> +
> +SYNOPSIS
> +--------
> +'git-archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]
> + [--remote=<repo>] <tree-ish> [path...]
> +
> +DESCRIPTION
> +-----------
> +Creates an archive of the specified format containing the tree
> +structure for the named tree. If <prefix> is specified it is
> +prepended to the filenames in the archive.
> +
> +'git-archive' behaves differently when given a tree ID versus when
> +given a commit ID or tag ID. In the first case the current time is
> +used as modification time of each file in the archive. In the latter
> +case the commit time as recorded in the referenced commit object is
> +used instead. Additionally the commit ID is stored in a global
> +extended pax header if the tar format is used; it can be extracted
> +using 'git-get-tar-commit-id'. In ZIP files it is stored as a file
> +comment.
> +
> +OPTIONS
> +-------
> +
> +--format=<fmt>::
> + Format of the resulting archive: 'tar', 'zip'...
> +
> +--list::
> + Show all available formats.
> +
> +--prefix=<prefix>/::
> + Prepend <prefix>/ to each filename in the archive.
> +
> +<extra>::
> + This can be any options that the archiver backend understand.
> +
> +--remote=<repo>::
> + Instead of making a tar archive from local repository,
> + retrieve a tar archive from a remote repository.
> +
> +<tree-ish>::
> + The tree or commit to produce an archive for.
> +
> +path::
> + If one or more paths are specified, include only these in the
> + archive, otherwise include all files and subdirectories.
> +
> +CONFIGURATION
> +-------------
> +By default, file and directories modes are set to 0666 or 0777 in tar
> +archives. It is possible to change this by setting the "umask" variable
> +in the repository configuration as follows :
> +
> +[tar]
> + umask = 002 ;# group friendly
> +
> +The special umask value "user" indicates that the user's current umask
> +will be used instead. The default value remains 0, which means world
> +readable/writable files and directories.
> +
> +EXAMPLES
> +--------
> +git archive --format=tar --prefix=junk/ HEAD | (cd /var/tmp/ && tar xf -)::
> +
> + Create a tar archive that contains the contents of the
> + latest commit on the current branch, and extracts it in
> + `/var/tmp/junk` directory.
> +
> +git archive --format=tar --prefix=git-1.4.0/ v1.4.0 | gzip >git-1.4.0.tar.gz::
> +
> + Create a compressed tarball for v1.4.0 release.
> +
> +git archive --format=tar --prefix=git-1.4.0/ v1.4.0{caret}\{tree\} | gzip >git-1.4.0.tar.gz::
> +
> + Create a compressed tarball for v1.4.0 release, but without a
> + global extended pax header.
> +
> +git archive --format=zip --prefix=git-docs/ HEAD:Documentation/ > git-1.4.0-docs.zip::
> +
> + Put everything in the current head's Documentation/ directory
> + into 'git-1.4.0-docs.zip', with the prefix 'git-docs/'.
> +
> +Author
> +------
> +Written by Franck Bui-Huu and Rene Scharfe.
> +
> +Documentation
> +--------------
> +Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
> +
> +GIT
> +---
> +Part of the gitlink:git[7] suite
> diff --git a/Makefile b/Makefile
> index 389daf7..51ed4dd 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -242,7 +242,7 @@ LIB_FILE=libgit.a
> XDIFF_LIB=xdiff/lib.a
>
> LIB_H = \
> - blob.h cache.h commit.h csum-file.h delta.h \
> + archive.h blob.h cache.h commit.h csum-file.h delta.h \
> diff.h object.h pack.h para-walk.h pkt-line.h quote.h refs.h \
> run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
> tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h
> @@ -267,6 +267,7 @@ LIB_OBJS = \
> BUILTIN_OBJS = \
> builtin-add.o \
> builtin-apply.o \
> + builtin-archive.o \
> builtin-cat-file.o \
> builtin-checkout-index.o \
> builtin-check-ref-format.o \
> diff --git a/archive.h b/archive.h
> new file mode 100644
> index 0000000..24b016f
> --- /dev/null
> +++ b/archive.h
> @@ -0,0 +1,41 @@
> +#ifndef ARCHIVE_H
> +#define ARCHIVE_H
> +
> +#define MAX_EXTRA_ARGS 32
> +#define MAX_ARGS (MAX_EXTRA_ARGS + 32)
> +
> +struct archiver_args {
> + const char *base;
> + struct tree *tree;
> + const unsigned char *commit_sha1;
> + time_t time;
> + const char **pathspec;
> + void *extra;
> +};
> +
> +typedef int (*write_archive_fn_t)(struct archiver_args *);
> +
> +typedef void *(*parse_extra_args_fn_t)(int argc, const char **argv);
> +
> +struct archiver {
> + const char *name;
> + const char *remote;
> + struct archiver_args args;
> + write_archive_fn_t write_archive;
> + parse_extra_args_fn_t parse_extra;
> +};
> +
> +extern struct archiver archivers[];
> +
> +extern int parse_archive_args(int argc,
> + const char **argv,
> + struct archiver *ar);
> +
> +extern void parse_treeish_arg(const char **treeish,
> + struct archiver_args *ar_args,
> + const char *prefix);
> +
> +extern void parse_pathspec_arg(const char **pathspec,
> + struct archiver_args *args);
> +
> +#endif /* ARCHIVE_H */
> diff --git a/builtin-archive.c b/builtin-archive.c
> new file mode 100644
> index 0000000..5671cbd
> --- /dev/null
> +++ b/builtin-archive.c
> @@ -0,0 +1,225 @@
> +/*
> + * Copyright (c) 2006 Franck Bui-Huu
> + * Copyright (c) 2006 Rene Scharfe
> + */
> +#include <time.h>
> +#include "cache.h"
> +#include "builtin.h"
> +#include "archive.h"
> +#include "commit.h"
> +#include "tree-walk.h"
> +#include "exec_cmd.h"
> +#include "pkt-line.h"
> +
> +static const char archive_usage[] = \
> +"git-archive --format=<fmt> [--prefix=<prefix>/] [<extra>] <tree-ish> [path...]";
> +
> +
> +struct archiver archivers[] = { };
> +
> +
> +static int run_remote_archiver(struct archiver *ar, int argc,
> + const char **argv)
> +{
> + char *url, buf[1024];
> + int fd[2], i, len, rv;
> + pid_t pid;
> +
> + sprintf(buf, "git-upload-archive");
> +
> + url = strdup(ar->remote);
xstrdup()
> + pid = git_connect(fd, url, buf);
> + if (pid < 0)
> + return pid;
> +
> + for (i = 1; i < argc; i++) {
> + if (!strncmp(argv[i], "--remote=", 9))
> + continue;
> + packet_write(fd[1], "argument %s\n", argv[i]);
> + }
> + packet_flush(fd[1]);
> +
> + len = packet_read_line(fd[0], buf, sizeof(buf));
> + if (!len)
> + die("git-archive: expected ACK/NAK, got EOF");
> + if (buf[len-1] == '\n')
> + buf[--len] = 0;
> + if (strcmp(buf, "ACK")) {
> + if (len > 5 && !strncmp(buf, "NACK ", 5))
> + die("git-archive: NACK %s", buf + 5);
> + die("git-archive: protocol error");
> + }
> +
> + len = packet_read_line(fd[0], buf, sizeof(buf));
> + if (len)
> + die("git-archive: expected a flush");
> +
> + /* Now, start reading from fd[0] and spit it out to stdout */
> + rv = copy_fd(fd[0], 1);
> +
> + close(fd[0]);
> + rv |= finish_connect(pid);
> +
> + return !!rv;
> +}
> +
> +static int init_archiver(const char *name, struct archiver *ar)
> +{
> + int rv = -1, i;
> +
> + for (i = 0; i < ARRAY_SIZE(archivers); i++) {
> + if (!strcmp(name, archivers[i].name)) {
> + memcpy(ar, &archivers[i], sizeof(struct archiver));
> + rv = 0;
> + break;
> + }
> + }
> + return rv;
> +}
> +
> +void parse_pathspec_arg(const char **pathspec, struct archiver_args *ar_args)
> +{
> + ar_args->pathspec = get_pathspec(ar_args->base, pathspec);
> +}
> +
> +void parse_treeish_arg(const char **argv, struct archiver_args *ar_args,
> + const char *prefix)
> +{
> + const char *name = argv[0];
> + const unsigned char *commit_sha1;
> + time_t archive_time;
> + struct tree *tree;
> + struct commit *commit;
> + unsigned char sha1[20];
> +
> + if (get_sha1(name, sha1))
> + die("Not a valid object name");
> +
> + commit = lookup_commit_reference_gently(sha1, 1);
> + if (commit) {
> + commit_sha1 = commit->object.sha1;
> + archive_time = commit->date;
> + } else {
> + archive_time = time(NULL);
> + }
> +
> + tree = parse_tree_indirect(sha1);
> + if (tree == NULL)
> + die("not a tree object");
> +
> + if (prefix) {
> + unsigned char tree_sha1[20];
> + unsigned int mode;
> + int err;
> +
> + err = get_tree_entry(tree->object.sha1, prefix,
> + tree_sha1, &mode);
> + if (err || !S_ISDIR(mode))
> + die("current working directory is untracked");
> +
> + free(tree);
> + tree = parse_tree_indirect(tree_sha1);
> + }
> + ar_args->tree = tree;
> + ar_args->commit_sha1 = commit_sha1;
> + ar_args->time = archive_time;
> +}
> +
> +static const char *default_parse_extra(struct archiver *ar,
> + const char **argv)
> +{
> + static char msg[64];
> +
> + snprintf(msg, sizeof(msg) - 4, "'%s' format does not handle %s",
> + ar->name, *argv);
> +
> + return strcat(msg, "...");
> +}
> +
> +int parse_archive_args(int argc, const char **argv, struct archiver *ar)
> +{
> + const char *extra_argv[MAX_EXTRA_ARGS];
> + int extra_argc = 0;
> + const char *format = NULL; /* some default values */
This comment does not convey any information.
> + const char *remote = NULL;
> + const char *base = "";
> + int list = 0;
> + int i;
> +
> + for (i = 1; i < argc; i++) {
> + const char *arg = argv[i];
> +
> + if (!strcmp(arg, "--list") || !strcmp(arg, "-l")) {
> + list = 1;
> + continue;
> + }
> + if (!strncmp(arg, "--format=", 9)) {
> + format = arg + 9;
> + continue;
> + }
> + if (!strncmp(arg, "--prefix=", 9)) {
> + base = arg + 9;
> + continue;
> + }
> + if (!strncmp(arg, "--remote=", 9)) {
> + remote = arg + 9;
> + continue;
> + }
> + if (!strcmp(arg, "--")) {
> + i++;
> + break;
> + }
> + if (arg[0] == '-') {
> + extra_argv[extra_argc++] = arg;
Overrun is not checked.
> + continue;
> + }
> + break;
> + }
> + if (list) {
> + if (!remote) {
> + for (i = 0; i < ARRAY_SIZE(archivers); i++)
> + printf("%s\n", archivers[i].name);
> + exit(0);
> + }
> + die("--list and --remote are mutually exclusive");
> + }
Not sure if we really need a list option. I guess it only really
makes sense if we have more than five formats. I have no _strong_
feelings against it, though. *shrug*
> + if (argc - i < 1) {
> + die("%s", archive_usage);
usage()
> + }
> + if (!format){
> + die("You must specify an archive format");
> + }
> + if (init_archiver(format, ar) < 0) {
> + die("Unknown archive format '%s'", format);
> + }
> + if (extra_argc && !remote) {
> + if (!ar->parse_extra) {
> + die("%s", default_parse_extra(ar, extra_argv));
> + }
> + ar->args.extra = ar->parse_extra(extra_argc, extra_argv);
> + }
> + ar->remote = remote;
> + ar->args.base = base;
> +
> + return i;
> +}
> +
> +int cmd_archive(int argc, const char **argv, const char *prefix)
> +{
> + struct archiver ar;
> + int tree_idx;
> +
> + tree_idx = parse_archive_args(argc, argv, &ar);
> +
> + if (ar.remote)
> + return run_remote_archiver(&ar, argc, argv);
> +
> + if (prefix == NULL)
> + prefix = setup_git_directory();
> +
> + argv += tree_idx;
> + parse_treeish_arg(argv, &ar.args, prefix);
> + parse_pathspec_arg(argv + 1, &ar.args);
> +
> + return ar.write_archive(&ar.args);
> +}
> diff --git a/builtin.h b/builtin.h
> index 8472c79..2391afb 100644
> --- a/builtin.h
> +++ b/builtin.h
> @@ -15,6 +15,7 @@ extern int write_tree(unsigned char *sha
>
> extern int cmd_add(int argc, const char **argv, const char *prefix);
> extern int cmd_apply(int argc, const char **argv, const char *prefix);
> +extern int cmd_archive(int argc, const char **argv, const char *prefix);
> extern int cmd_cat_file(int argc, const char **argv, const char *prefix);
> extern int cmd_checkout_index(int argc, const char **argv, const char *prefix);
> extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
> diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
> index ec1eda2..5450918 100755
> --- a/generate-cmdlist.sh
> +++ b/generate-cmdlist.sh
> @@ -12,6 +12,7 @@ struct cmdname_help common_cmds[] = {"
> sort <<\EOF |
> add
> apply
> +archive
> bisect
> branch
> checkout
> diff --git a/git.c b/git.c
> index 82c8fee..c62c5cf 100644
> --- a/git.c
> +++ b/git.c
> @@ -218,6 +218,7 @@ static void handle_internal_command(int
> } commands[] = {
> { "add", cmd_add, RUN_SETUP },
> { "apply", cmd_apply },
> + { "archive", cmd_archive },
> { "cat-file", cmd_cat_file, RUN_SETUP },
> { "checkout-index", cmd_checkout_index, RUN_SETUP },
> { "check-ref-format", cmd_check_ref_format },
^ permalink raw reply
* Re: [PATCH 1/2] Add git-archive
From: Rene Scharfe @ 2006-09-08 20:21 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <ednb29$u0u$1@sea.gmane.org>
Jakub Narebski schrieb:
> Rene Scharfe wrote:
>
>> IMHO should work like in the following example, and the code above
>> cuts off the Documentation part:
>>
>> $ cd Documentation $ git-archive --format=tar --prefix=v1.0/ HEAD howto | tar tf -
>> v1.0/howto/
>> v1.0/howto/isolate-bugs-with-bisect.txt ...
>>
>> I agree that simple subtree matching would be enough, at least for
>> now.
>
> What about
>
> $ git-archive --format=tar --prefix=v1.0/ HEAD:Documentation/howto
That is fine, too (cutting off Documentation/howto).
My comment above was about the piece of code that handles cd'ing around in
the repository. git-tar-tree ignores the current working directory -- you
always get the full tree put into your tar file, and you have to do the
"trick" you mentioned if you want to archive only a subtree. This is a bit
strange, so I think we should do it right from the start in git-archive.
René
^ permalink raw reply
* Re: [PATCH 2/4] git-archive: wire up TAR format.
From: Rene Scharfe @ 2006-09-08 20:21 UTC (permalink / raw)
To: Franck Bui-Huu; +Cc: junkio, git
In-Reply-To: <11576347252834-git-send-email-vagabon.xyz@gmail.com>
Franck Bui-Huu schrieb:
> From: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
>
> Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
> Signed-off-by: Franck Bui-Huu <vagabon.xyz@gmail.com>
I did not sign off this exact patch. I wrote and submitted the
builtin-tar-tree.c part, with memory leak and all, then sent a note
on where the leak needs to be plugged. You put it together and
converted it to struct archiver_args. I'd very much have liked to
see a comment stating this. Or simply just say "based on code by
Rene" or something. The same is true for patch 3/4.
> ---
> archive.h | 4 +++
> builtin-archive.c | 4 ++-
> builtin-tar-tree.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 74 insertions(+), 1 deletions(-)
>
> diff --git a/archive.h b/archive.h
> index f33398e..3690c53 100644
> --- a/archive.h
> +++ b/archive.h
> @@ -37,5 +37,9 @@ extern void parse_treeish_arg(const char
>
> extern void parse_pathspec_arg(const char **pathspec,
> struct archiver_args *args);
> +/*
> + *
> + */
Especially I would not have signed off this invisible comment. ;)
René
^ permalink raw reply
* Re: gitweb: Add committags support
From: Jakub Narebski @ 2006-09-08 20:57 UTC (permalink / raw)
To: git
In-Reply-To: <200609081246.56423.jnareb@gmail.com>
Jakub Narebski wrote:
> our %committags = (
> 'commitsha' => {
> 'pattern' => qr/[0-9a-fA-F]{40}/,
> 'sub' => sub {
> my $hash_text = shift;
> if (git_get_type($hash_text) eq "commit") {
> return
> $cgi->a({-href => href(action=>"commit", hash=>$hash_text),
> -class => "text"}, $hash_text);
> }
> return undef;
> },
> 'islink' => 1,
> },
> 'mantis' => {
> 'pattern' => qr/(BUG|FEATURE)\(\d+\)/,
> 'options' => [ 'http://bugs.xmms2.xmms.se/view.php?id=' ],
> 'sub' => sub {
> my $match = shift;
> my $URL = shift;
> my ($issue) = $match =~ /(\d+)/;
> return
> $cgi->a({-href => "$URL$issue"},
> $match);
> },
> 'islink' => 1,
> },
> );
Yet another committag:
'URL' => { # simple URL, no query strings
# because of the whole esc_html() + ' '->' ' thing
'pattern' => qr!(http|ftp)s?://[a-zA-Z0-9%./]+!,
'sub' => sub {
my $url = shift;
return
$cgi->a({-href => $url},
$url); # should be perhaps shortened
},
'islink' => 1,
},
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* Re: Change set based shallow clone
From: Jon Smirl @ 2006-09-08 21:13 UTC (permalink / raw)
To: linux@horizon.com; +Cc: git
In-Reply-To: <20060908184215.31789.qmail@science.horizon.com>
> > Here is another way to look at the shallow clone problem. The only
> > public ids in a git tree are the head and tag pointers. Send these to
> > the client. Now let's modify the git tools to fault the full objects
> > in one by one from the server whenever a git operation needs the
> > object. Dangling references would point to 'not-present' objects.
>
> Er... that would fault in a gigabyte the first time someone ran gitk,
> or several other history-browsing commands. Don't you need a way to say
> "tell the user this isn't present and will take an hour to download"?
gitk would need to be modified to only run enough of the commit tree
to draw what is displayed in the window. As you page down it would
retrive more commits if needed. There is no need for gitk to run 250K
commits when I'm usually never going to look at them all. Of course
this may mean some rework for gitk.
--
Jon Smirl
jonsmirl@gmail.com
^ permalink raw reply
* Re: [PATCH] Move color option parsing out of diff.c and into color.[ch]
From: Junio C Hamano @ 2006-09-08 21:19 UTC (permalink / raw)
To: Jeff King; +Cc: git
In-Reply-To: <20060908091206.GA5758@coredump.intra.peff.net>
Jeff King <peff@peff.net> writes:
> I'm assuming you can mark both of those up yourself rather than having
> me resend?
Sure, that's easy enough.
Thanks for the patch.
^ permalink raw reply
* Problem with send-email
From: Timur Tabi @ 2006-09-08 21:11 UTC (permalink / raw)
To: git
I'm having two problems with git-send-email.
Problem #1:
I don't know Perl, but I think there's something wrong with this code:
if (!defined $from) {
$from = $author || $committer;
print "$from\n";
do {
$_ = $term->readline("Who should the emails appear to be from? ",
$from);
} while (!defined $_);
$from = $_;
print "Emails will be sent from: ", $from, "\n";
$prompting++;
}
I don't think the call to readline() is working. Specifically, the last parameter, $from, is being ignored. When I call git-send-email without specifying a --from parameter, this code is executed. But this is what I see:
Timur Tabi <timur@freescale.com>
Who should the emails appear to be from?
Emails will be sent from:
This happens when I press ENTER at the "Who should the emails appear to be from?" prompt. I'm expecting it to assign the default value, which is displayed right above it. But instead, $from is erased, and so my email doesn't have a From: line.
Problem #2:
I cannot use send-email to send a patch to anyone but myself. If I do this:
git-send-email --from timur@freescale.com --to timur@freescale.com --smtp-server remotesmtp.freescale.net patchfile
Everything works. However, if I do this:
git-send-email --from timur@freescale.com --to --smtp-server remotesmtp.freescale.net patchfile
I get this:
(mbox) Adding cc: Timur Tabi <timur@freescale.com> from line 'From: Timur Tabi <timur@freescale.com>'
(sob) Adding cc: Timur Tabi <timur@freescale.com> from line 'Signed-off-by: Timur Tabi <timur@freescale.com>'
5.0.0 <Timur Tabi <timur@freescale.com>... Unbalanced '<'
I think that last line is a response from the SMTP server. My guess is that there's something wrong with this line:
print $sm "$header\n$message";
Maybe my SMTP server sees the "From: Timur Tabi <timur@freescale.com>" that's at the top of $message and gets confused?
--
Timur Tabi
Linux Kernel Developer @ Freescale
^ permalink raw reply
* Problem with send-email
From: Timur Tabi @ 2006-09-08 21:04 UTC (permalink / raw)
To: git
Does anyone actually use git-send-email? It's been so broken for me for months that I can't help but think that.
Problem #1:
I don't know Perl, but I think there's something wrong with this code:
if (!defined $from) {
$from = $author || $committer;
print "$from\n";
do {
$_ = $term->readline("Who should the emails appear to be from? ",
$from);
} while (!defined $_);
$from = $_;
print "Emails will be sent from: ", $from, "\n";
$prompting++;
}
I don't think the call to readline() is working. Specifically, the last parameter, $from, is being ignored. When I call git-send-email without specifying a --from parameter, this code is executed. But this is what I see:
Timur Tabi <timur@freescale.com>
Who should the emails appear to be from?
Emails will be sent from:
This happens when I press ENTER at the "Who should the emails appear to be from?" prompt. I'm expecting it to assign the default value, which is displayed right above it. But instead, $from is erased, and so my email doesn't have a From: line.
Problem #2:
I cannot use send-email to send a patch to anyone but myself. If I do this:
git-send-email --from timur@freescale.com --to timur@freescale.com --smtp-server remotesmtp.freescale.net patchfile
Everything works. However, if I do this:
git-send-email --from timur@freescale.com --to --smtp-server remotesmtp.freescale.net patchfile
I get this:
(mbox) Adding cc: Timur Tabi <timur@freescale.com> from line 'From: Timur Tabi <timur@freescale.com>'
(sob) Adding cc: Timur Tabi <timur@freescale.com> from line 'Signed-off-by: Timur Tabi <timur@freescale.com>'
5.0.0 <Timur Tabi <timur@freescale.com>... Unbalanced '<'
I think that last line is a response from the SMTP server. My guess is that there's something wrong with this line:
print $sm "$header\n$message";
Maybe my SMTP server sees the "From: Timur Tabi <timur@freescale.com>" that's at the top of $message and gets confused?
--
Timur Tabi
Linux Kernel Developer @ Freescale
^ permalink raw reply
* Problem with send-email
From: Timur Tabi @ 2006-09-08 21:13 UTC (permalink / raw)
To: git
I'm having two problems with git-send-email.
Problem #1:
I don't know Perl, but I think there's something wrong with this code:
if (!defined $from) {
$from = $author || $committer;
print "$from\n";
do {
$_ = $term->readline("Who should the emails appear to be from? ",
$from);
} while (!defined $_);
$from = $_;
print "Emails will be sent from: ", $from, "\n";
$prompting++;
}
I don't think the call to readline() is working. Specifically, the last parameter, $from, is being ignored. When I call git-send-email without specifying a --from parameter, this code is executed. But this is what I see:
Timur Tabi <timur@freescale.com>
Who should the emails appear to be from?
Emails will be sent from:
This happens when I press ENTER at the "Who should the emails appear to be from?" prompt. I'm expecting it to assign the default value, which is displayed right above it. But instead, $from is erased, and so my email doesn't have a From: line.
Problem #2:
I cannot use send-email to send a patch to anyone but myself. If I do this:
git-send-email --from timur@freescale.com --to timur@freescale.com --smtp-server remotesmtp.freescale.net patchfile
Everything works. However, if I do this:
git-send-email --from timur@freescale.com --to --smtp-server remotesmtp.freescale.net patchfile
I get this:
(mbox) Adding cc: Timur Tabi <timur@freescale.com> from line 'From: Timur Tabi <timur@freescale.com>'
(sob) Adding cc: Timur Tabi <timur@freescale.com> from line 'Signed-off-by: Timur Tabi <timur@freescale.com>'
5.0.0 <Timur Tabi <timur@freescale.com>... Unbalanced '<'
I think that last line is a response from the SMTP server. My guess is that there's something wrong with this line:
print $sm "$header\n$message";
Maybe my SMTP server sees the "From: Timur Tabi <timur@freescale.com>" that's at the top of $message and gets confused?
--
Timur Tabi
Linux Kernel Developer @ Freescale
^ permalink raw reply
* Problem with send-email
From: Timur Tabi @ 2006-09-08 21:02 UTC (permalink / raw)
To: git
Does anyone actually use git-send-email? It's been so broken for me for months that I can't help but think that.
Problem #1:
I don't know Perl, but I think there's something wrong with this code:
if (!defined $from) {
$from = $author || $committer;
print "$from\n";
do {
$_ = $term->readline("Who should the emails appear to be from? ",
$from);
} while (!defined $_);
$from = $_;
print "Emails will be sent from: ", $from, "\n";
$prompting++;
}
I don't think the call to readline() is working. Specifically, the last parameter, $from, is being ignored. When I call git-send-email without specifying a --from parameter, this code is executed. But this is what I see:
Timur Tabi <timur@freescale.com>
Who should the emails appear to be from?
Emails will be sent from:
This happens when I press ENTER at the "Who should the emails appear to be from?" prompt. I'm expecting it to assign the default value, which is displayed right above it. But instead, $from is erased, and so my email doesn't have a From: line.
Problem #2:
I cannot use send-email to send a patch to anyone but myself. If I do this:
git-send-email --from timur@freescale.com --to timur@freescale.com --smtp-server remotesmtp.freescale.net patchfile
Everything works. However, if I do this:
git-send-email --from timur@freescale.com --to --smtp-server remotesmtp.freescale.net patchfile
I get this:
(mbox) Adding cc: Timur Tabi <timur@freescale.com> from line 'From: Timur Tabi <timur@freescale.com>'
(sob) Adding cc: Timur Tabi <timur@freescale.com> from line 'Signed-off-by: Timur Tabi <timur@freescale.com>'
5.0.0 <Timur Tabi <timur@freescale.com>... Unbalanced '<'
I think that last line is a response from the SMTP server. My guess is that there's something wrong with this line:
print $sm "$header\n$message";
Maybe my SMTP server sees the "From: Timur Tabi <timur@freescale.com>" that's at the top of $message and gets confused?
--
Timur Tabi
Linux Kernel Developer @ Freescale
^ permalink raw reply
* Re: Problem with send-email
From: Timur Tabi @ 2006-09-08 21:35 UTC (permalink / raw)
To: git
In-Reply-To: <4501DCDD.4020403@freescale.com>
Sorry about the reposts, but my company's email server told me it rejected my posts because it thought they were spam. I wasn't expecting the server to hold on to them and them send them out later.
--
Timur Tabi
Linux Kernel Developer @ Freescale
^ permalink raw reply
* Re: Add git-archive [take #2]
From: Junio C Hamano @ 2006-09-08 21:42 UTC (permalink / raw)
To: Franck; +Cc: git
In-Reply-To: <45013B5A.8000301@innova-card.com>
Franck Bui-Huu <vagabon.xyz@gmail.com> writes:
> Sorry I was speaking about the git protocol. It has been included
> in master branch.
I do not think so. The recent "master" history is like this
(look at "gitk --full-history v1.4.2..master -- daemon.c"):
d819e4e daemon: prepare for multiple services
This introduced the daemon_service[] table and run_service
facility. The service table contained upload-pack only.
This was merged into "master" and pushed out with
1efca00 Merge early part of branch 'jc/daemon'
At this point, 'jc/daemon' topic branch contained the d819e4e
above and this one, which added upload-tar to the service table:
74c0cc2 daemon: add upload-tar service.
this was part of "next" but was not in "master". This made
"tar-tree --remote" against git-daemon usable in "next". But
before I pushed this out to "master", upload-archive design you
and Rene were working on became a lot more promising and
attractive. Especially, discussion with Rene made me realize
that redoing upload-xxx protocol for each archiver was not a
good design. So I did:
d9edcbd Revert "daemon: add upload-tar service."
on 'jc/daemon' branch. And then that topic was merged into
"master" and pushed out, because that will allow you and Rene to
work your patch against "master" which would be nicer to not
just you but to everybody -- other people can test your patches
before they hit my tree on any branch.
In other words,
> git tar-tree --remote=git://anything/repo.git
never worked in "master". At least that is how I wanted the
commit ancestry graph to look like and why the above merges and
reverts were done in the order described above.
Once git archive hits "master", we should announce that "git
tar-tree" and "git zip-tree" are deprecated, and we will remove
them sometime later. As part of the same announcement we could
say that "git tar-tree --remote" works with transports other
than git-daemon, but we do not plan to add git native transport
support to it before its removal, because "git archive" is
preferred method both on local and remote archiving from then
on.
^ permalink raw reply
* Re: Add git-archive [take #2]
From: Junio C Hamano @ 2006-09-08 21:42 UTC (permalink / raw)
To: Rene Scharfe; +Cc: git
In-Reply-To: <4501D0B8.8060103@lsrfire.ath.cx>
Rene Scharfe <rene.scharfe@lsrfire.ath.cx> writes:
> Junio C Hamano schrieb:
>> Franck Bui-Huu <vagabon.xyz@gmail.com> writes:
>>
>>> 1/ Allow 'git-upload-archive' command to enable/disable some
>>> formats. This should be done by 'git-upload-archive'.
>>
>> Perhaps. I was thinking about the way how a site administrator can
>> configure such when upload-archive is spawned via git-daemon (for
>> users coming from ssh and spawn an upload-archive on their own, it's
>> their own process and upload-archive has no business deciding what is
>> allowed and what is forbidden). Not very many clean ways I can
>> think of unfortunately.
>
> Mmpf, ssh is (one of the things) in my blind spot. Do you mean a
> ssh+git-shell connection? One could argue that since this is a
> restricted connection anyway upload-archive _has_ a right to restrict
> archive format etc., too. On a full, unrestricted ssh connection one
> can start git-archive directly. I'd do that anyway because I'm used to
> do this with tar. ;-)
Ah, I was not thinking about git-shell and it might want to be
restrictive.
> ... Mmh, maybe an environment variable
> which is set by the daemon can be used? This is no dirtier than what
> webservers do..
Exactly my thought, except "no dirtier" part I did not think
through but now you said it I tend to agree.
So site administrator can ask git-daemon to export some
environment variable that git-upload-archive notices and
restrict service. If we choose to we can add a similar facility
to set the same environment variable to git-shell, so services
to retricted ssh users can be limited the same way by the
administrator. That sounds like a good plan; we do not have
to do that for git-shell until somebody asks.
^ permalink raw reply
* Re: [PATCH 2/4] git-archive: wire up TAR format.
From: Junio C Hamano @ 2006-09-08 21:42 UTC (permalink / raw)
To: Rene Scharfe; +Cc: git, Franck Bui-Huu
In-Reply-To: <4501D0CF.70306@lsrfire.ath.cx>
Rene Scharfe <rene.scharfe@lsrfire.ath.cx> writes:
> I did not sign off this exact patch. I wrote and submitted the
> builtin-tar-tree.c part, with memory leak and all, then sent a note
> on where the leak needs to be plugged. You put it together and
> converted it to struct archiver_args. I'd very much have liked to
> see a comment stating this. Or simply just say "based on code by
> Rene" or something. The same is true for patch 3/4.
>...
Thanks for clarification -- I also was wondering if you two were
working as a team exchanging drafts and the message I saw was
the fruit of such collaboration (like the way Johannes/Alex team
worked on C rewrite of merge-recursive). Otherwise the sign-off
was indeed inappropriate.
>> +/*
>> + *
>> + */
>
> Especially I would not have signed off this invisible comment. ;)
I take your response is a mild NAK.
^ permalink raw reply
* Re: git refuses to switch to older branches
From: Alex Riesen @ 2006-09-08 22:00 UTC (permalink / raw)
To: Martin Waitz; +Cc: Junio C Hamano, git
In-Reply-To: <20060820121935.GF30022@admingilde.org>
Sorry for the answer long overdue, I was on vacation, and quite off
of the internet.
Martin Waitz, Sun, Aug 20, 2006 14:19:35 +0200:
> On Sun, Aug 20, 2006 at 09:26:12AM +0200, Alex Riesen wrote:
> > Junio C Hamano, Sun, Aug 20, 2006 00:39:20 +0200:
> > > Martin Waitz <tali@admingilde.org> writes:
> > >
> > > > This safety measure is quite useful normally, but for files that are
> > > > explicitly marked as to-be-ignored it should not be neccessary.
> > > >
> > > > But all the code that handles .gitignore is only used by ls-files now.
> > > > Does it make sense to add exclude handling to unpack-trees.c, too?
> > >
> > > In principle, I am not opposed to the idea of making read-tree
> > > take the ignore information into consideration.
> > >
> > > But I would suggest you to be _extremely_ careful if you want to
> >
> > It should be optional. And off by default, people already have got
> > scripts depending on this behaviour (well, I have).
>
> but having this sort of behaviour optional is bad, I think.
> Some people will depend on one semantic and others on the other.
> And then get bite if they want to share their scripts.
So at least give the people who got there first a chance to have
their scripts working. Why break them?
> We have to find _one_ semantic that always works.
Well, the current semantics always work.
> > > try this. I do not have an example offhand, but I would not be
> > > surprised at all if there is a valid use case where it is useful
> > > to have a pattern that matches a tracked file in .gitignore
> > > file.
> >
> > Ignored directory and but some files/subdirectories in it are tracked,
> > because this is temporary or externally changed data (I have both
> > examples).
>
> but do you have non-tracked files in the ignored directory that you
> really care about, i.e. which must not be overridden by a tracked file
> with the same name?
>
I don't, but I can easily imagine someone has: a file contained some
build-local configuration, which developer later decided to start
tracking. Like config.mak in git.
^ permalink raw reply
* Re: Problem with send-email
From: Jakub Narebski @ 2006-09-08 22:25 UTC (permalink / raw)
To: git
In-Reply-To: <4501DA6D.9020104@freescale.com>
Timur Tabi wrote:
> Everything works. However, if I do this:
>
> git-send-email --from timur@freescale.com --to \
> --smtp-server remotesmtp.freescale.net patchfile
>
What do you expect when you specify _empty_ To: header?
I use git-send-email from time to time; I always specify From:,
either entering it when prompted, or using --from parameter.
The fact that it didn't fill default value from committer/author
core.author+core.email is I guess a bug...
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* Re: Change set based shallow clone
From: Jakub Narebski @ 2006-09-08 22:27 UTC (permalink / raw)
To: git
In-Reply-To: <9e4733910609081413p32456768g280bdc9b232d7902@mail.gmail.com>
Jon Smirl wrote:
>> > Here is another way to look at the shallow clone problem. The only
>> > public ids in a git tree are the head and tag pointers. Send these to
>> > the client. Now let's modify the git tools to fault the full objects
>> > in one by one from the server whenever a git operation needs the
>> > object. Dangling references would point to 'not-present' objects.
>>
>> Er... that would fault in a gigabyte the first time someone ran gitk,
>> or several other history-browsing commands. Don't you need a way to say
>> "tell the user this isn't present and will take an hour to download"?
>
> gitk would need to be modified to only run enough of the commit tree
> to draw what is displayed in the window. As you page down it would
> retrive more commits if needed. There is no need for gitk to run 250K
> commits when I'm usually never going to look at them all. Of course
> this may mean some rework for gitk.
Or remembering to set --max-count or --max-age parameters to gitk (which are
then passed to git-rev-list).
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* Re: Problem with send-email
From: Timur Tabi @ 2006-09-08 22:57 UTC (permalink / raw)
To: git
In-Reply-To: <edsqjo$gh3$1@sea.gmane.org>
Jakub Narebski wrote:
> Timur Tabi wrote:
>
>> Everything works. However, if I do this:
>>
>> git-send-email --from timur@freescale.com --to \
>> --smtp-server remotesmtp.freescale.net patchfile
>>
>
> What do you expect when you specify _empty_ To: header?
Sorry, that was a bad cut-and-paste. I don't know what happened. That line is supposed to read:
git-send-email --from timur@freescale.com --to timur@tabi.org --smtp-server remotesmtp.freescale.net patchfile
The error message I get is the same:
(mbox) Adding cc: Timur Tabi <timur@freescale.com> from line 'From: Timur Tabi <timur@freescale.com>'
(sob) Adding cc: Timur Tabi <timur@freescale.com> from line 'Signed-off-by: Timur Tabi <timur@freescale.com>
'
5.0.0 <Timur Tabi <timur@freescale.com>... Unbalanced '<'
I do have some news. This problem goes away if I don't specify the --smtp-server parameter.
>
> I use git-send-email from time to time; I always specify From:,
> either entering it when prompted, or using --from parameter.
> The fact that it didn't fill default value from committer/author
> core.author+core.email is I guess a bug...
Like I said, I think the bug is in the call to readline(). Like I said, I don't know Perl, but from the documentation I have read, I don't think readline() takes two parameters.
do {
$_ = $term->readline("Who should the emails appear to be from? ",
$from);
} while (!defined $_);
$from = $_;
$from does contain the correct value when readline() is called. The problem is that $_ contains nothing, which causes $from to be erased.
--
Timur Tabi
Linux Kernel Developer @ Freescale
^ permalink raw reply
* Re: Some issues with current qgit on exit ( aka "Crash this!" )
From: Marco Costalba @ 2006-09-08 23:03 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
>
> > I was planning (well, still I am) to release new version this week
> > end, and your bug report is arrived just in time ;-)
>
> I tried to push qgit a bit harder, and it's still easy to crash:
>
Thanks for reporting, bug (a subtle one this time) fixed and patch pushed.
I don't think you or someone else could crash qgit anymore ;-)
Thanks
Marco
^ permalink raw reply
* Re: Change set based shallow clone
From: Linus Torvalds @ 2006-09-08 23:09 UTC (permalink / raw)
To: Jon Smirl; +Cc: linux@horizon.com, Git Mailing List, Paul Mackerras
In-Reply-To: <9e4733910609081413p32456768g280bdc9b232d7902@mail.gmail.com>
On Fri, 8 Sep 2006, Jon Smirl wrote:
>
> gitk would need to be modified to only run enough of the commit tree
> to draw what is displayed in the window. As you page down it would
> retrive more commits if needed. There is no need for gitk to run 250K
> commits when I'm usually never going to look at them all. Of course
> this may mean some rework for gitk.
Actually, it's more than a little rework.
The _real_ problem is that gitk uses "--topo-order" to git-rev-list, which
basically means that git-rev-list needs to parse EVERY SINGLE COMMIT.
So far, nobody has written a topological sort that can reasonably
efficiently handle partial trees and automatically notice when there is no
way that a DAG cannot have any more references to a commit any more (if
you can show that the result would cause a cycle, you could output a
partial topological tree early).
It's possible that no such topological sorting (ie the efficient kind,
that can work with partial DAG's) even exists.
So if you want to be able to visualize a partial repository, you need to
teach git to not need "--topo-order" first. That's likely the _big_
change. After that, the rest should be easy.
[ One way to do it might be: the normal ordering of revisions without
"--topo-order) is "_close_ to topological", and gitk could just decide
to re-compute the whole graph whenever it gets a commit that has a
parent that it has already graphed. Done right, it would probably almost
never actually generate re-computed graphs (if you only actually
generate the graph when the user scrolls down to it).
Getting rid of the --topo-order requirement would speed up gitk
absolutely immensely, especially for unpacked cold-cache archives. So it
would probably be a good thing to do, regardless of any shallow clone
issues ]
Hmm?
Linus
^ permalink raw reply
* Re: Some issues with current qgit on exit ( aka "Crash this!" )
From: Pavel Roskin @ 2006-09-08 23:25 UTC (permalink / raw)
To: Marco Costalba; +Cc: git
In-Reply-To: <e5bfff550609081603s2fb1be98gdafb91681a4aeaae@mail.gmail.com>
Hi, Marco!
On Sat, 2006-09-09 at 01:03 +0200, Marco Costalba wrote:
> >
> Thanks for reporting, bug (a subtle one this time) fixed and patch pushed.
>
> I don't think you or someone else could crash qgit anymore ;-)
Wow, I've been clicking on it for 5 minutes like crazy, yet qgit didn't
crash! Neither did it crash on exit.
However, qgit has produced some output you may find interesting:
[proski@dv qgit]$ qgit
ASSERT in lookupAnnotation: no annotation for src/git_startup.cpp
ASSERT in lookupAnnotation: no annotation for src/fileview.cpp
ASSERT in lookupAnnotation: no annotation for src/git.cpp
ASSERT in lookupAnnotation: no annotation for src/mainbase.ui
[proski@dv qgit]$
This message is quite easy to reproduce by "crazy clicking", but I
cannot do it if clicking slowing and noting what I'm doing. I guess
it's a timing issue - something must happen before the annotations are
loaded.
--
Regards,
Pavel Roskin
^ permalink raw reply
* Re: Change set based shallow clone
From: Jon Smirl @ 2006-09-08 23:28 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux@horizon.com, Git Mailing List, Paul Mackerras
In-Reply-To: <Pine.LNX.4.64.0609081600530.27779@g5.osdl.org>
On 9/8/06, Linus Torvalds <torvalds@osdl.org> wrote:
> Getting rid of the --topo-order requirement would speed up gitk
> absolutely immensely, especially for unpacked cold-cache archives. So it
> would probably be a good thing to do, regardless of any shallow clone
> issues ]
>
> Hmm?
gitk takes about a minute to come up on the Mozilla repo when
everything is in cache. It takes about twice as long when things are
cold. It's enough of delay that I don't use the tool.
>
> Linus
>
--
Jon Smirl
jonsmirl@gmail.com
^ permalink raw reply
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