11
#include "dir.h"
12
#include "packfile.h"
13
#include "help.h"
14
-#include "archive.h"
15
-#include "object-store.h"
16
-#include "compat/disk.h"
14
+#include "diagnose.h"
15
16
/*
17
* Remove the deepest subdirectory in the provided path string. Path must not
261
return res;
262
}
263
266
-static int add_directory_to_archiver(struct strvec *archiver_args,
267
- const char *path, int recurse)
268
-{
269
- int at_root = !*path;
270
- DIR *dir;
271
- struct dirent *e;
272
- struct strbuf buf = STRBUF_INIT;
273
- size_t len;
274
- int res = 0;
275
-
276
- dir = opendir(at_root ? "." : path);
277
- if (!dir) {
278
- if (errno == ENOENT) {
279
- warning(_("could not archive missing directory '%s'"), path);
280
- return 0;
281
- }
282
- return error_errno(_("could not open directory '%s'"), path);
283
- }
284
-
285
- if (!at_root)
286
- strbuf_addf(&buf, "%s/", path);
287
- len = buf.len;
288
- strvec_pushf(archiver_args, "--prefix=%s", buf.buf);
289
-
290
- while (!res && (e = readdir(dir))) {
291
- if (!strcmp(".", e->d_name) || !strcmp("..", e->d_name))
292
- continue;
293
-
294
- strbuf_setlen(&buf, len);
295
- strbuf_addstr(&buf, e->d_name);
296
-
297
- if (e->d_type == DT_REG)
298
- strvec_pushf(archiver_args, "--add-file=%s", buf.buf);
299
- else if (e->d_type != DT_DIR)
300
- warning(_("skipping '%s', which is neither file nor "
301
- "directory"), buf.buf);
302
- else if (recurse &&
303
- add_directory_to_archiver(archiver_args,
304
- buf.buf, recurse) < 0)
305
- res = -1;
306
- }
307
-
308
- closedir(dir);
309
- strbuf_release(&buf);
310
- return res;
311
-}
312
-
264
/* printf-style interface, expects `<key>=<value>` argument */
265
static int set_config(const char *fmt, ...)
266
{
501
return res;
502
}
503
553
-static void dir_file_stats_objects(const char *full_path, size_t full_path_len,
554
- const char *file_name, void *data)
555
-{
556
- struct strbuf *buf = data;
557
- struct stat st;
558
-
559
- if (!stat(full_path, &st))
560
- strbuf_addf(buf, "%-70s %16" PRIuMAX "\n", file_name,
561
- (uintmax_t)st.st_size);
562
-}
563
-
564
-static int dir_file_stats(struct object_directory *object_dir, void *data)
565
-{
566
- struct strbuf *buf = data;
567
-
568
- strbuf_addf(buf, "Contents of %s:\n", object_dir->path);
569
-
570
- for_each_file_in_pack_dir(object_dir->path, dir_file_stats_objects,
571
- data);
572
-
573
- return 0;
574
-}
575
-
576
-static int count_files(char *path)
577
-{
578
- DIR *dir = opendir(path);
579
- struct dirent *e;
580
- int count = 0;
581
-
582
- if (!dir)
583
- return 0;
584
-
585
- while ((e = readdir(dir)) != NULL)
586
- if (!is_dot_or_dotdot(e->d_name) && e->d_type == DT_REG)
587
- count++;
588
-
589
- closedir(dir);
590
- return count;
591
-}
592
-
593
-static void loose_objs_stats(struct strbuf *buf, const char *path)
594
-{
595
- DIR *dir = opendir(path);
596
- struct dirent *e;
597
- int count;
598
- int total = 0;
599
- unsigned char c;
600
- struct strbuf count_path = STRBUF_INIT;
601
- size_t base_path_len;
602
-
603
- if (!dir)
604
- return;
605
-
606
- strbuf_addstr(buf, "Object directory stats for ");
607
- strbuf_add_absolute_path(buf, path);
608
- strbuf_addstr(buf, ":\n");
609
-
610
- strbuf_add_absolute_path(&count_path, path);
611
- strbuf_addch(&count_path, '/');
612
- base_path_len = count_path.len;
613
-
614
- while ((e = readdir(dir)) != NULL)
615
- if (!is_dot_or_dotdot(e->d_name) &&
616
- e->d_type == DT_DIR && strlen(e->d_name) == 2 &&
617
- !hex_to_bytes(&c, e->d_name, 1)) {
618
- strbuf_setlen(&count_path, base_path_len);
619
- strbuf_addstr(&count_path, e->d_name);
620
- total += (count = count_files(count_path.buf));
621
- strbuf_addf(buf, "%s : %7d files\n", e->d_name, count);
622
- }
623
-
624
- strbuf_addf(buf, "Total: %d loose objects", total);
625
-
626
- strbuf_release(&count_path);
627
- closedir(dir);
628
-}
629
-
504
static int cmd_diagnose(int argc, const char **argv)
505
{
506
struct option options[] = {
511
NULL
512
};
513
struct strbuf zip_path = STRBUF_INIT;
640
- struct strvec archiver_args = STRVEC_INIT;
641
- char **argv_copy = NULL;
642
- int stdout_fd = -1, archiver_fd = -1;
514
time_t now = time(NULL);
515
struct tm tm;
645
- struct strbuf buf = STRBUF_INIT;
516
int res = 0;
517
518
argc = parse_options(argc, argv, NULL, options,
533
zip_path.buf);
534
goto diagnose_cleanup;
535
}
666
- stdout_fd = dup(1);
667
- if (stdout_fd < 0) {
668
- res = error_errno(_("could not duplicate stdout"));
669
- goto diagnose_cleanup;
670
- }
671
-
672
- archiver_fd = xopen(zip_path.buf, O_CREAT | O_WRONLY | O_TRUNC, 0666);
673
- if (archiver_fd < 0 || dup2(archiver_fd, 1) < 0) {
674
- res = error_errno(_("could not redirect output"));
675
- goto diagnose_cleanup;
676
- }
677
-
678
- init_zip_archiver();
679
- strvec_pushl(&archiver_args, "scalar-diagnose", "--format=zip", NULL);
680
-
681
- strbuf_reset(&buf);
682
- strbuf_addstr(&buf, "Collecting diagnostic info\n\n");
683
- get_version_info(&buf, 1);
684
-
685
- strbuf_addf(&buf, "Enlistment root: %s\n", the_repository->worktree);
686
- get_disk_info(&buf);
687
- write_or_die(stdout_fd, buf.buf, buf.len);
688
- strvec_pushf(&archiver_args,
689
- "--add-virtual-file=diagnostics.log:%.*s",
690
- (int)buf.len, buf.buf);
691
-
692
- strbuf_reset(&buf);
693
- strbuf_addstr(&buf, "--add-virtual-file=packs-local.txt:");
694
- dir_file_stats(the_repository->objects->odb, &buf);
695
- foreach_alt_odb(dir_file_stats, &buf);
696
- strvec_push(&archiver_args, buf.buf);
697
-
698
- strbuf_reset(&buf);
699
- strbuf_addstr(&buf, "--add-virtual-file=objects-local.txt:");
700
- loose_objs_stats(&buf, ".git/objects");
701
- strvec_push(&archiver_args, buf.buf);
702
-
703
- if ((res = add_directory_to_archiver(&archiver_args, ".git", 0)) ||
704
- (res = add_directory_to_archiver(&archiver_args, ".git/hooks", 0)) ||
705
- (res = add_directory_to_archiver(&archiver_args, ".git/info", 0)) ||
706
- (res = add_directory_to_archiver(&archiver_args, ".git/logs", 1)) ||
707
- (res = add_directory_to_archiver(&archiver_args, ".git/objects/info", 0)))
708
- goto diagnose_cleanup;
709
-
710
- strvec_pushl(&archiver_args, "--prefix=",
711
- oid_to_hex(the_hash_algo->empty_tree), "--", NULL);
712
-
713
- /* `write_archive()` modifies the `argv` passed to it. Let it. */
714
- argv_copy = xmemdupz(archiver_args.v,
715
- sizeof(char *) * archiver_args.nr);
716
- res = write_archive(archiver_args.nr, (const char **)argv_copy, NULL,
717
- the_repository, NULL, 0);
718
- if (res) {
719
- error(_("failed to write archive"));
720
- goto diagnose_cleanup;
721
- }
536
723
- if (!res)
724
- fprintf(stderr, "\n"
725
- "Diagnostics complete.\n"
726
- "All of the gathered info is captured in '%s'\n",
727
- zip_path.buf);
537
+ res = create_diagnostics_archive(&zip_path);
538
539
diagnose_cleanup:
730
- if (archiver_fd >= 0) {
731
- close(1);
732
- dup2(stdout_fd, 1);
733
- }
734
- free(argv_copy);
735
- strvec_clear(&archiver_args);
540
strbuf_release(&zip_path);
737
- strbuf_release(&buf);
738
-
541
return res;
542
}
543