Hash :
a0bf6e76
Author :
Date :
2019-03-15T16:35:47
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
/*
* Copyright (c) 2018, 2019 Stefan Sperling <stsp@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* State information for a tracked file in a work tree.
* When written to disk, multi-byte fields are written in big-endian.
* Some fields are based on results from stat(2). These are only used in
* order to detect modifications made to on-disk files, they are never
* applied back to the filesystem.
*/
struct got_fileindex_entry {
RB_ENTRY(got_fileindex_entry) entry;
uint64_t ctime_sec;
uint64_t ctime_nsec;
uint64_t mtime_sec;
uint64_t mtime_nsec;
uint32_t uid;
uint32_t gid;
/*
* On-disk size is truncated to the lower 32 bits.
* The value is only used to check for modifications anyway.
*/
uint32_t size;
uint16_t mode;
#define GOT_FILEIDX_MODE_FILE_TYPE 0x000f
#define GOT_FILEIDX_MODE_REGULAR_FILE 1
#define GOT_FILEIDX_MODE_SYMLINK 2
#define GOT_FILEIDX_MODE_PERMS 0xff10
#define GOT_FILEIDX_MODE_PERMS_SHIFT 4
/* SHA1 of corresponding blob in repository. */
uint8_t blob_sha1[SHA1_DIGEST_LENGTH];
/* SHA1 of corresponding base commit in repository. */
uint8_t commit_sha1[SHA1_DIGEST_LENGTH];
uint32_t flags;
#define GOT_FILEIDX_F_PATH_LEN 0x00000fff
#define GOT_FILEIDX_F_STAGE 0x00003000
#define GOT_FILEIDX_F_EXTENDED 0x00004000
#define GOT_FILEIDX_F_ASSUME_VALID 0x00008000
#define GOT_FILEIDX_F_NOT_ON_DISK 0x20000000
/*
* UNIX-style path, relative to work tree root.
* Variable length, and NUL-padded to a multiple of 8 on disk.
*/
char *path;
/* More data could be here if F_EXTENDED is set; To be determined... */
};
/* "Stages" of a file afflicted by a 3-way merge conflict. */
#define GOT_FILEIDX_STAGE_MERGED 0
#define GOT_FILEIDX_STAGE_ANCESTOR 1
#define GOT_FILEIDX_STAGE_OURS 2
#define GOT_FILEIDX_STAGE_THEIRS 3
struct got_fileindex;
RB_HEAD(got_fileindex_tree, got_fileindex_entry);
static inline int
got_fileindex_cmp(const struct got_fileindex_entry *e1,
const struct got_fileindex_entry *e2)
{
return got_path_cmp(e1->path, e2->path);
}
RB_PROTOTYPE(got_fileindex_tree, got_fileindex_entry, entry, got_fileindex_cmp);
/* On-disk file index header structure. */
struct got_fileindex_hdr {
uint32_t signature; /* big-endian */
#define GOT_FILE_INDEX_SIGNATURE 0x676f7449 /* 'g', 'o', 't', 'I' */
uint32_t version; /* big-endian */
#define GOT_FILE_INDEX_VERSION 1
uint32_t nentries; /* big-endian */
/* list of concatenated fileindex entries */
uint8_t sha1[SHA1_DIGEST_LENGTH]; /* checksum of above on-disk data */
};
const struct got_error *got_fileindex_entry_update(struct got_fileindex_entry *,
const char *, uint8_t *, uint8_t *, int);
const struct got_error *got_fileindex_entry_alloc(struct got_fileindex_entry **,
const char *, const char *, uint8_t *, uint8_t *);
void got_fileindex_entry_free(struct got_fileindex_entry *);
struct got_fileindex *got_fileindex_alloc(void);
void got_fileindex_free(struct got_fileindex *);
const struct got_error *got_fileindex_write(struct got_fileindex *, FILE *);
const struct got_error *got_fileindex_entry_add(struct got_fileindex *,
struct got_fileindex_entry *);
void got_fileindex_entry_remove(struct got_fileindex *,
struct got_fileindex_entry *);
struct got_fileindex_entry *got_fileindex_entry_get(struct got_fileindex *,
const char *);
const struct got_error *got_fileindex_read(struct got_fileindex *, FILE *);
typedef const struct got_error *(*got_fileindex_cb)(void *,
struct got_fileindex_entry *);
const struct got_error *got_fileindex_for_each_entry_safe(
struct got_fileindex *, got_fileindex_cb cb, void *);
typedef const struct got_error *(*got_fileindex_diff_tree_old_new_cb)(void *,
struct got_fileindex_entry *, struct got_tree_entry *, const char *);
typedef const struct got_error *(*got_fileindex_diff_tree_old_cb)(void *,
struct got_fileindex_entry *, const char *);
typedef const struct got_error *(*got_fileindex_diff_tree_new_cb)(void *,
struct got_tree_entry *, const char *);
struct got_fileindex_diff_tree_cb {
got_fileindex_diff_tree_old_new_cb diff_old_new;
got_fileindex_diff_tree_old_cb diff_old;
got_fileindex_diff_tree_new_cb diff_new;
};
const struct got_error *got_fileindex_diff_tree(struct got_fileindex *,
struct got_tree_object *, struct got_repository *,
struct got_fileindex_diff_tree_cb *, void *);
typedef const struct got_error *(*got_fileindex_diff_dir_old_new_cb)(void *,
struct got_fileindex_entry *, struct dirent *, const char *);
typedef const struct got_error *(*got_fileindex_diff_dir_old_cb)(void *,
struct got_fileindex_entry *, const char *);
typedef const struct got_error *(*got_fileindex_diff_dir_new_cb)(void *,
struct dirent *, const char *);
struct got_fileindex_diff_dir_cb {
got_fileindex_diff_dir_old_new_cb diff_old_new;
got_fileindex_diff_dir_old_cb diff_old;
got_fileindex_diff_dir_new_cb diff_new;
};
const struct got_error *got_fileindex_diff_dir(struct got_fileindex *, DIR *,
const char *, const char *, struct got_repository *,
struct got_fileindex_diff_dir_cb *, void *);