commit 9e672c7443bebadbd8806c9a4366543f852eb372 from: Stefan Sperling date: Mon Mar 11 14:03:28 2019 UTC implement got_ref_write() commit - f02eaa22e5963774a1ad9810e415ab201552ec8c commit + 9e672c7443bebadbd8806c9a4366543f852eb372 blob - ee6fe6460a2a0de9ae5395eb0de8571d8aa8a135 blob + a0d4587d54e186ee756ec2c4e91ce23ca709d5c4 --- got/Makefile +++ got/Makefile @@ -5,7 +5,7 @@ SRCS= got.c blame.c commit_graph.c delta.c diff.c dif diffreg.c error.c fileindex.c object.c object_cache.c \ object_idset.c object_parse.c opentemp.c path.c pack.c \ privsep.c reference.c repository.c sha1.c worktree.c \ - inflate.c buf.c worklist.c rcsutil.c diff3.c + inflate.c buf.c worklist.c rcsutil.c diff3.c lockfile.c CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib \ -DGOT_LIBEXECDIR=${GOT_LIBEXECDIR} blob - dfb265d33164e060c796c1de3b3ad9f85bb27bb7 blob + 6f15ea20735cffc58ec67eb8b358eecaab8360d5 --- include/got_reference.h +++ include/got_reference.h @@ -73,3 +73,7 @@ SIMPLEQ_HEAD(got_reflist_head, got_reflist_entry); /* Append all known references to a caller-provided ref list head. */ const struct got_error *got_ref_list(struct got_reflist_head *, struct got_repository *); + +/* Write a reference to its on-disk path in the repository. */ +const struct got_error *got_ref_write(struct got_reference *, + struct got_repository *); blob - 9e9655183bf6af53d89c2fcea53352d7d2a47b3e blob + 18fca1ae9be06a6b5840128d6f6bc4454d04ab49 --- lib/reference.c +++ lib/reference.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -31,6 +32,7 @@ #include "got_object.h" #include "got_repository.h" #include "got_reference.h" +#include "got_opentemp.h" #include "got_lib_sha1.h" #include "got_lib_path.h" @@ -696,3 +698,90 @@ done: err = got_error_from_errno(); return err; } + +const struct got_error * +got_ref_write(struct got_reference *ref, struct got_repository *repo) +{ + const struct got_error *err = NULL, *unlock_err = NULL; + const char *name = got_ref_get_name(ref); + char *path_refs = NULL, *path = NULL, *tmppath = NULL; + struct got_lockfile *lf = NULL; + FILE *f = NULL; + size_t n; + struct stat sb; + + path_refs = get_refs_dir_path(repo, name); + if (path_refs == NULL) { + err = got_error_from_errno(); + goto done; + } + + if (asprintf(&path, "%s/%s", path_refs, name) == -1) { + err = got_error_from_errno(); + goto done; + } + + err = got_opentemp_named(&tmppath, &f, path); + if (f == NULL) { + err = got_error_from_errno(); + goto done; + } + + if (ref->flags & GOT_REF_IS_SYMBOLIC) { + n = fprintf(f, "ref: %s\n", ref->ref.symref.ref); + if (n != strlen(ref->ref.symref.ref) + 6) { + err = got_ferror(f, GOT_ERR_IO); + goto done; + } + } else { + char hex[SHA1_DIGEST_STRING_LENGTH]; + if (got_sha1_digest_to_str(ref->ref.ref.sha1, hex, + sizeof(hex)) == NULL) { + err = got_error(GOT_ERR_BAD_REF_DATA); + goto done; + } + n = fprintf(f, "%s\n", hex); + if (n != sizeof(hex) + 1) { + err = got_ferror(f, GOT_ERR_IO); + goto done; + } + } + + err = got_lockfile_lock(&lf, path); + if (err) + goto done; + + /* XXX: check if old content matches our expectations? */ + + if (stat(path, &sb) != 0) { + err = got_error_from_errno(); + goto done; + } + + if (rename(tmppath, path) != 0) { + err = got_error_from_errno(); + goto done; + } + free(tmppath); + tmppath = NULL; + + if (chmod(path, sb.st_mode) != 0) { + err = got_error_from_errno(); + goto done; + } +done: + if (lf) + unlock_err = got_lockfile_unlock(lf); + if (f) { + if (fclose(f) != 0 && err == NULL) + err = got_error_from_errno(); + } + free(path_refs); + free(path); + if (tmppath) { + if (unlink(tmppath) != 0 && err == NULL) + err = got_error_from_errno(); + free(tmppath); + } + return err ? err : unlock_err; +} blob - 8fb53dfe4ebce9973fd7098c98914117b3baf3bf blob + f9ca31289f75c7ae7b0173ad9c02ced0b74ee558 --- regress/idset/Makefile +++ regress/idset/Makefile @@ -4,7 +4,7 @@ PROG = idset_test SRCS = error.c object.c privsep.c sha1.c pack.c inflate.c path.c opentemp.c \ delta.c repository.c reference.c worktree.c fileindex.c object_cache.c \ object_idset.c object_parse.c idset_test.c \ - buf.c worklist.c rcsutil.c diff.c diffreg.c diff3.c + buf.c worklist.c rcsutil.c diff.c diffreg.c diff3.c lockfile.c CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib LDADD = -lutil -lz blob - d75f821ba3e7ed1050713ad1cc994f972eda1ee1 blob + 77226c0a9e382144bb29cf3d1b4c85432d485d37 --- regress/repository/Makefile +++ regress/repository/Makefile @@ -4,7 +4,7 @@ PROG = repository_test SRCS = path.c repository.c error.c reference.c object.c object_cache.c \ object_idset.c object_parse.c opentemp.c sha1.c diff.c diffreg.c \ pack.c privsep.c delta.c fileindex.c worktree.c inflate.c \ - buf.c worklist.c rcsutil.c diff3.c \ + buf.c worklist.c rcsutil.c diff3.c lockfile.c \ repository_test.c CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib \ blob - 21476afed2b0930f65f44d151ae98a2ba3c55081 blob + 1f297d962fc7317a131f0a9fe1c790fc0512c7b7 --- regress/worktree/Makefile +++ regress/worktree/Makefile @@ -4,7 +4,7 @@ PROG = worktree_test SRCS = worktree.c repository.c object.c object_cache.c object_idset.c \ object_parse.c opentemp.c path.c error.c reference.c sha1.c pack.c \ privsep.c delta.c inflate.c fileindex.c \ - buf.c worklist.c rcsutil.c diff.c diffreg.c diff3.c \ + buf.c worklist.c rcsutil.c diff.c diffreg.c diff3.c lockfile.c \ worktree_test.c CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib \ blob - 87516af1da37593f11b27b5440b5d09a61937e7e blob + 144d8da5ec3fc100ce967fcaf1c1aca1d07660e7 --- tog/Makefile +++ tog/Makefile @@ -5,7 +5,8 @@ SRCS= tog.c blame.c commit_graph.c delta.c diff.c dif diffreg.c error.c fileindex.c object.c object_cache.c \ object_idset.c object_parse.c opentemp.c path.c pack.c \ privsep.c reference.c repository.c sha1.c worktree.c \ - utf8.c inflate.c buf.c worklist.c rcsutil.c diff3.c + utf8.c inflate.c buf.c worklist.c rcsutil.c diff3.c \ + lockfile.c CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib \ -DGOT_LIBEXECDIR=${GOT_LIBEXECDIR}