diff mbox series

[v2,3/6] object-file.c: handle nil oid in write_loose_object()

Message ID 20211112094010.73468-3-chiyutianyi@gmail.com (mailing list archive)
State New, archived
Headers show
Series unpack-objects: unpack large object in stream | expand

Commit Message

Han Xin Nov. 12, 2021, 9:40 a.m. UTC
From: Han Xin <hanxin.hx@alibaba-inc.com>

When read input stream, oid can't get before reading all, and it will be
filled after reading.

Helped-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>
Signed-off-by: Han Xin <hanxin.hx@alibaba-inc.com>
---
 object-file.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

Comments

Jiang Xin Nov. 18, 2021, 5:49 a.m. UTC | #1
On Fri, Nov 12, 2021 at 5:42 PM Han Xin <chiyutianyi@gmail.com> wrote:
>
> From: Han Xin <hanxin.hx@alibaba-inc.com>
>
> When read input stream, oid can't get before reading all, and it will be
> filled after reading.

Under what circumstances is the oid a null oid?  Can we get the oid
from “obj_list[nr].oid” ?
See unpack_non_delta_entry() of builtin/unpack-objects.c.

> Helped-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>
> Signed-off-by: Han Xin <hanxin.hx@alibaba-inc.com>
> ---
>  object-file.c | 34 ++++++++++++++++++++++++++++++++--
>  1 file changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/object-file.c b/object-file.c
> index b0838c847e..8393659f0d 100644
> --- a/object-file.c
> +++ b/object-file.c
> @@ -1893,7 +1893,13 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
>         const char *buf;
>         unsigned long len;
>
> -       loose_object_path(the_repository, &filename, oid);
> +       if (is_null_oid(oid)) {
> +               /* When oid is not determined, save tmp file to odb path. */
> +               strbuf_reset(&filename);
> +               strbuf_addstr(&filename, the_repository->objects->odb->path);
> +               strbuf_addch(&filename, '/');
> +       } else
> +               loose_object_path(the_repository, &filename, oid);
>
>         if (!dry_run) {
>                 fd = create_tmpfile(&tmp_file, filename.buf);
> @@ -1942,7 +1948,7 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
>                 die(_("deflateEnd on object %s failed (%d)"), oid_to_hex(oid),
>                     ret);
>         the_hash_algo->final_oid_fn(&parano_oid, &c);
> -       if (!oideq(oid, &parano_oid))
> +       if (!is_null_oid(oid) && !oideq(oid, &parano_oid))
>                 die(_("confused by unstable object source data for %s"),
>                     oid_to_hex(oid));
>
> @@ -1951,6 +1957,30 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
>
>         close_loose_object(fd);
>
> +       if (is_null_oid(oid)) {
> +               int dirlen;
> +
> +               /* copy oid */
> +               oidcpy((struct object_id *)oid, &parano_oid);
> +               /* We get the oid now */
> +               loose_object_path(the_repository, &filename, oid);
> +
> +               dirlen = directory_size(filename.buf);
> +               if (dirlen) {
> +                       struct strbuf dir = STRBUF_INIT;
> +                       /*
> +                        * Make sure the directory exists; note that the
> +                        * contents of the buffer are undefined after mkstemp
> +                        * returns an error, so we have to rewrite the whole
> +                        * buffer from scratch.
> +                        */
> +                       strbuf_reset(&dir);
> +                       strbuf_add(&dir, filename.buf, dirlen - 1);
> +                       if (mkdir(dir.buf, 0777) && errno != EEXIST)
> +                               return -1;
> +               }
> +       }
> +
>         if (mtime) {
>                 struct utimbuf utb;
>                 utb.actime = mtime;
> --
> 2.33.1.44.g9344627884.agit.6.5.4
>
diff mbox series

Patch

diff --git a/object-file.c b/object-file.c
index b0838c847e..8393659f0d 100644
--- a/object-file.c
+++ b/object-file.c
@@ -1893,7 +1893,13 @@  static int write_loose_object(const struct object_id *oid, char *hdr,
 	const char *buf;
 	unsigned long len;
 
-	loose_object_path(the_repository, &filename, oid);
+	if (is_null_oid(oid)) {
+		/* When oid is not determined, save tmp file to odb path. */
+		strbuf_reset(&filename);
+		strbuf_addstr(&filename, the_repository->objects->odb->path);
+		strbuf_addch(&filename, '/');
+	} else
+		loose_object_path(the_repository, &filename, oid);
 
 	if (!dry_run) {
 		fd = create_tmpfile(&tmp_file, filename.buf);
@@ -1942,7 +1948,7 @@  static int write_loose_object(const struct object_id *oid, char *hdr,
 		die(_("deflateEnd on object %s failed (%d)"), oid_to_hex(oid),
 		    ret);
 	the_hash_algo->final_oid_fn(&parano_oid, &c);
-	if (!oideq(oid, &parano_oid))
+	if (!is_null_oid(oid) && !oideq(oid, &parano_oid))
 		die(_("confused by unstable object source data for %s"),
 		    oid_to_hex(oid));
 
@@ -1951,6 +1957,30 @@  static int write_loose_object(const struct object_id *oid, char *hdr,
 
 	close_loose_object(fd);
 
+	if (is_null_oid(oid)) {
+		int dirlen;
+
+		/* copy oid */
+		oidcpy((struct object_id *)oid, &parano_oid);
+		/* We get the oid now */
+		loose_object_path(the_repository, &filename, oid);
+
+		dirlen = directory_size(filename.buf);
+		if (dirlen) {
+			struct strbuf dir = STRBUF_INIT;
+			/*
+			 * Make sure the directory exists; note that the
+			 * contents of the buffer are undefined after mkstemp
+			 * returns an error, so we have to rewrite the whole
+			 * buffer from scratch.
+			 */
+			strbuf_reset(&dir);
+			strbuf_add(&dir, filename.buf, dirlen - 1);
+			if (mkdir(dir.buf, 0777) && errno != EEXIST)
+				return -1;
+		}
+	}
+
 	if (mtime) {
 		struct utimbuf utb;
 		utb.actime = mtime;