| 792 | } |
| 793 | |
| 794 | struct packed_git *add_packed_git(struct repository *r, const char *path, |
| 795 | size_t path_len, int local) |
| 796 | { |
| 797 | struct stat st; |
| 798 | size_t alloc; |
| 799 | struct packed_git *p; |
| 800 | struct object_id oid; |
| 801 | |
| 802 | /* |
| 803 | * Make sure a corresponding .pack file exists and that |
| 804 | * the index looks sane. |
| 805 | */ |
| 806 | if (!strip_suffix_mem(path, &path_len, ".idx")) |
| 807 | return NULL; |
| 808 | |
| 809 | /* |
| 810 | * ".promisor" is long enough to hold any suffix we're adding (and |
| 811 | * the use xsnprintf double-checks that) |
| 812 | */ |
| 813 | alloc = st_add3(path_len, strlen(".promisor"), 1); |
| 814 | p = alloc_packed_git(r, alloc); |
| 815 | memcpy(p->pack_name, path, path_len); |
| 816 | |
| 817 | /* |
| 818 | * Note that we have to check auxiliary data structures before we check |
| 819 | * for the ".pack" file to exist to avoid races with a packfile that is |
| 820 | * in the process of being deleted. The ".pack" file is unlinked before |
| 821 | * its auxiliary data structures, so we know that we either get a |
| 822 | * consistent snapshot of all data structures or that we'll fail to |
| 823 | * stat(3p) the packfile itself and thus return `NULL`. |
| 824 | * |
| 825 | * As such, we cannot bail out before the access(3p) calls in case the |
| 826 | * packfile doesn't exist without doing two stat(3p) calls for it. |
| 827 | */ |
| 828 | xsnprintf(p->pack_name + path_len, alloc - path_len, ".keep"); |
| 829 | if (!access(p->pack_name, F_OK)) |
| 830 | p->pack_keep = 1; |
| 831 | |
| 832 | xsnprintf(p->pack_name + path_len, alloc - path_len, ".promisor"); |
| 833 | if (!access(p->pack_name, F_OK)) |
| 834 | p->pack_promisor = 1; |
| 835 | |
| 836 | xsnprintf(p->pack_name + path_len, alloc - path_len, ".mtimes"); |
| 837 | if (!access(p->pack_name, F_OK)) |
| 838 | p->is_cruft = 1; |
| 839 | |
| 840 | xsnprintf(p->pack_name + path_len, alloc - path_len, ".pack"); |
| 841 | if (stat(p->pack_name, &st) || !S_ISREG(st.st_mode)) { |
| 842 | free(p); |
| 843 | return NULL; |
| 844 | } |
| 845 | |
| 846 | /* ok, it looks sane as far as we can check without |
| 847 | * actually mapping the pack file. |
| 848 | */ |
| 849 | p->pack_size = st.st_size; |
| 850 | p->pack_local = local; |
| 851 | p->mtime = st.st_mtime; |
no test coverage detected