static int blob_create_internal(git_oid *oid, git_repository *repo, const char *content_path, const char *hint_path, bool try_load_filters) { int error; struct stat st; git_odb *odb = NULL; git_off_t size; assert(hint_path || !try_load_filters); if ((error = git_path_lstat(content_path, &st)) < 0 || (error = git_repository_odb__weakptr(&odb, repo)) < 0) return error; size = st.st_size; if (S_ISLNK(st.st_mode)) { error = write_symlink(oid, odb, content_path, (size_t)size); } else { git_vector write_filters = GIT_VECTOR_INIT; int filter_count = 0; if (try_load_filters) { /* Load the filters for writing this file to the ODB */ filter_count = git_filters_load( &write_filters, repo, hint_path, GIT_FILTER_TO_ODB); } if (filter_count < 0) { /* Negative value means there was a critical error */ error = filter_count; } else if (filter_count == 0) { /* No filters need to be applied to the document: we can stream * directly from disk */ error = write_file_stream(oid, odb, content_path, size); } else { /* We need to apply one or more filters */ error = write_file_filtered(oid, odb, content_path, &write_filters); } git_filters_free(&write_filters); /* * TODO: eventually support streaming filtered files, for files * which are bigger than a given threshold. This is not a priority * because applying a filter in streaming mode changes the final * size of the blob, and without knowing its final size, the blob * cannot be written in stream mode to the ODB. * * The plan is to do streaming writes to a tempfile on disk and then * opening streaming that file to the ODB, using * `write_file_stream`. * * CAREFULLY DESIGNED APIS YO */ } return error; }
int git_blob__create_from_paths( git_oid *id, struct stat *out_st, git_repository *repo, const char *content_path, const char *hint_path, mode_t hint_mode, bool try_load_filters) { int error; struct stat st; git_odb *odb = NULL; git_off_t size; mode_t mode; git_buf path = GIT_BUF_INIT; assert(hint_path || !try_load_filters); if (!content_path) { if (git_repository__ensure_not_bare(repo, "create blob from file") < 0) return GIT_EBAREREPO; if (git_buf_joinpath( &path, git_repository_workdir(repo), hint_path) < 0) return -1; content_path = path.ptr; } if ((error = git_path_lstat(content_path, &st)) < 0 || (error = git_repository_odb(&odb, repo)) < 0) goto done; if (S_ISDIR(st.st_mode)) { giterr_set(GITERR_ODB, "cannot create blob from '%s': it is a directory", content_path); error = GIT_EDIRECTORY; goto done; } if (out_st) memcpy(out_st, &st, sizeof(st)); size = st.st_size; mode = hint_mode ? hint_mode : st.st_mode; if (S_ISLNK(mode)) { error = write_symlink(id, odb, content_path, (size_t)size); } else { git_filter_list *fl = NULL; if (try_load_filters) /* Load the filters for writing this file to the ODB */ error = git_filter_list_load( &fl, repo, NULL, hint_path, GIT_FILTER_TO_ODB, GIT_FILTER_DEFAULT); if (error < 0) /* well, that didn't work */; else if (fl == NULL) /* No filters need to be applied to the document: we can stream * directly from disk */ error = write_file_stream(id, odb, content_path, size); else { /* We need to apply one or more filters */ error = write_file_filtered(id, &size, odb, content_path, fl); git_filter_list_free(fl); } /* * TODO: eventually support streaming filtered files, for files * which are bigger than a given threshold. This is not a priority * because applying a filter in streaming mode changes the final * size of the blob, and without knowing its final size, the blob * cannot be written in stream mode to the ODB. * * The plan is to do streaming writes to a tempfile on disk and then * opening streaming that file to the ODB, using * `write_file_stream`. * * CAREFULLY DESIGNED APIS YO */ } done: git_odb_free(odb); git_buf_dispose(&path); return error; }
static void recursive_populate_directory(struct filesystem_entry *dir) { struct filesystem_entry *e; unsigned int wrote; if (verbose) { printf("%s\n", dir->fullname); } write_xattr_entry(dir); /* for '/' */ e = dir->files; while (e) { switch (e->sb.st_mode & S_IFMT) { case S_IFDIR: if (verbose) { printf("\td %04o %9lu %5d:%-3d %s\n", e->sb.st_mode & ~S_IFMT, e->sb.st_size, (int) (e->sb.st_uid), (int) (e->sb.st_gid), e->name); } write_pipe(e); write_xattr_entry(e); break; case S_IFSOCK: if (verbose) { printf("\ts %04o %9lu %5d:%-3d %s\n", e->sb.st_mode & ~S_IFMT, e->sb.st_size, (int) e->sb.st_uid, (int) e->sb.st_gid, e->name); } write_pipe(e); write_xattr_entry(e); break; case S_IFIFO: if (verbose) { printf("\tp %04o %9lu %5d:%-3d %s\n", e->sb.st_mode & ~S_IFMT, e->sb.st_size, (int) e->sb.st_uid, (int) e->sb.st_gid, e->name); } write_pipe(e); write_xattr_entry(e); break; case S_IFCHR: if (verbose) { printf("\tc %04o %4d,%4d %5d:%-3d %s\n", e->sb.st_mode & ~S_IFMT, major(e->sb.st_rdev), minor(e->sb.st_rdev), (int) e->sb.st_uid, (int) e->sb.st_gid, e->name); } write_special_file(e); write_xattr_entry(e); break; case S_IFBLK: if (verbose) { printf("\tb %04o %4d,%4d %5d:%-3d %s\n", e->sb.st_mode & ~S_IFMT, major(e->sb.st_rdev), minor(e->sb.st_rdev), (int) e->sb.st_uid, (int) e->sb.st_gid, e->name); } write_special_file(e); write_xattr_entry(e); break; case S_IFLNK: if (verbose) { printf("\tl %04o %9lu %5d:%-3d %s -> %s\n", e->sb.st_mode & ~S_IFMT, e->sb.st_size, (int) e->sb.st_uid, (int) e->sb.st_gid, e->name, e->link); } write_symlink(e); write_xattr_entry(e); break; case S_IFREG: wrote = write_regular_file(e); write_xattr_entry(e); if (verbose) { printf("\tf %04o %9lu (%9u) %5d:%-3d %s\n", e->sb.st_mode & ~S_IFMT, e->sb.st_size, wrote, (int) e->sb.st_uid, (int) e->sb.st_gid, e->name); } break; default: error_msg("Unknown mode %o for %s", e->sb.st_mode, e->fullname); break; } e = e->next; } e = dir->files; while (e) { if (S_ISDIR(e->sb.st_mode)) { if (e->files) { recursive_populate_directory(e); } else if (verbose) { printf("%s\n", e->fullname); } } e = e->next; } }