On Tue, May 10 2022, Johannes Schindelin via GitGitGadget wrote: > From: Johannes Schindelin <johannes.schindelin@xxxxxx> > > Over the course of Scalar's development, it became obvious that there is > a need for a command that can gather all kinds of useful information > that can help identify the most typical problems with large > worktrees/repositories. > > The `diagnose` command is the culmination of this hard-won knowledge: it > gathers the installed hooks, the config, a couple statistics describing > the data shape, among other pieces of information, and then wraps > everything up in a tidy, neat `.zip` archive. > > Note: originally, Scalar was implemented in C# using the .NET API, where > we had the luxury of a comprehensive standard library that includes > basic functionality such as writing a `.zip` file. In the C version, we > lack such a commodity. Rather than introducing a dependency on, say, > libzip, we slightly abuse Git's `archive` machinery: we write out a > `.zip` of the empty try, augmented by a couple files that are added via > the `--add-file*` options. We are careful trying not to modify the > current repository in any way lest the very circumstances that required > `scalar diagnose` to be run are changed by the `diagnose` run itself. > > Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx> > --- > contrib/scalar/scalar.c | 144 +++++++++++++++++++++++++++++++ > contrib/scalar/scalar.txt | 12 +++ > contrib/scalar/t/t9099-scalar.sh | 14 +++ > 3 files changed, 170 insertions(+) > > diff --git a/contrib/scalar/scalar.c b/contrib/scalar/scalar.c > index 00dcd4b50ef..367a2c50e25 100644 > --- a/contrib/scalar/scalar.c > +++ b/contrib/scalar/scalar.c > @@ -11,6 +11,7 @@ > #include "dir.h" > #include "packfile.h" > #include "help.h" > +#include "archive.h" > > /* > * Remove the deepest subdirectory in the provided path string. Path must not > @@ -261,6 +262,47 @@ static int unregister_dir(void) > return res; > } > > +static int add_directory_to_archiver(struct strvec *archiver_args, > + const char *path, int recurse) > +{ > + int at_root = !*path; > + DIR *dir = opendir(at_root ? "." : path); > + struct dirent *e; > + struct strbuf buf = STRBUF_INIT; > + size_t len; > + int res = 0; > + > + if (!dir) > + return error(_("could not open directory '%s'"), path); s/error/error_errno/, surely? > + strbuf_addstr(&zip_path, "/.scalarDiagnostics/scalar_"); > + strbuf_addftime(&zip_path, > + "%Y%m%d_%H%M%S", localtime_r(&now, &tm), 0, 0); Would we be worse off if we stole this timestamp from some known file (or HEAD), and thus made a second run of this reproducable?