Count tracked files via git ls-files */
| 774 | |
| 775 | /* Count tracked files via git ls-files */ |
| 776 | static watcher_git_status_t git_file_count(cbm_watcher_t *w, project_state_t *state, |
| 777 | int *count_out) { |
| 778 | if (!count_out) { |
| 779 | return WATCHER_GIT_SUPERVISION_FAILED; |
| 780 | } |
| 781 | *count_out = 0; |
| 782 | const char *argv[] = {"git", "-C", state->root_path, "ls-files", "-z", NULL}; |
| 783 | watcher_git_output_t output; |
| 784 | watcher_git_status_t status = watcher_git_run(w, state, argv, WATCHER_GIT_OUTPUT_MAX, &output); |
| 785 | if (status != WATCHER_GIT_OK) { |
| 786 | return status; |
| 787 | } |
| 788 | FILE *fp = cbm_fopen(output.path, "rb"); |
| 789 | if (!fp) { |
| 790 | watcher_git_output_cleanup(&output); |
| 791 | return WATCHER_GIT_SUPERVISION_FAILED; |
| 792 | } |
| 793 | |
| 794 | /* NUL mode is unambiguous even for tracked filenames containing newlines. */ |
| 795 | int count = 0; |
| 796 | char buf[CBM_SZ_1K]; |
| 797 | size_t n; |
| 798 | while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) { |
| 799 | for (size_t i = 0; i < n; i++) { |
| 800 | if (buf[i] == '\0' && count < INT_MAX) { |
| 801 | count++; |
| 802 | } |
| 803 | } |
| 804 | } |
| 805 | if (ferror(fp) || fclose(fp) != 0) { |
| 806 | watcher_git_output_cleanup(&output); |
| 807 | return WATCHER_GIT_SUPERVISION_FAILED; |
| 808 | } |
| 809 | watcher_git_output_cleanup(&output); |
| 810 | *count_out = count; |
| 811 | return WATCHER_GIT_OK; |
| 812 | } |
| 813 | |
| 814 | /* ── Project state lifecycle ────────────────────────────────────── */ |
| 815 |
no test coverage detected