AmendHub

Download:

jcs

/

amend

/

amendments

/

42

repo: New repo version 3, switching to bile files

No migration at this time, it's done with a different program

jcs made amendment 42 over 2 years ago
--- repo.c Thu Dec 30 16:47:41 2021 +++ repo.c Tue Jan 11 19:40:43 2022 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 joshua stein <jcs@jcs.org> + * Copyright (c) 2021-2022 joshua stein <jcs@jcs.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,11 +19,12 @@ #include <time.h> #include "amend.h" +#include "bile.h" #include "diff.h" #include "repo.h" #include "util.h" -struct repo *repo_init(SFReply reply, short is_new); +struct repo * repo_init(struct bile *bile, short is_new); void repo_sort_files(struct repo *repo); void repo_sort_commits(struct repo *repo); short repo_get_file_attrs(struct repo *repo, Str255 filename, @@ -39,6 +40,7 @@ repo_open(AppFile *file) Point pt = { 75, 100 }; SFReply reply; SFTypeList types; + struct bile *bile; if (file) { reply.vRefNum = file->vRefNum; @@ -51,7 +53,16 @@ repo_open(AppFile *file) return NULL; } - return repo_init(reply, 0); + bile = bile_open(reply.fName, reply.vRefNum); + if (bile == NULL) { + warn("Opening repo %s failed: %d", PtoCstr(reply.fName), + bile_error(NULL)); + return NULL; + } + + bile_fsck(bile); + + return repo_init(bile, 0); } struct repo * @@ -59,88 +70,86 @@ repo_create(void) { Point pt = { 75, 100 }; SFReply reply; - char *newpath = NULL; + struct bile *bile; short error, fh, i; SFPutFile(pt, "\pCreate new repository:", "\p", NULL, &reply); if (!reply.good) return NULL; - - getpath(reply.vRefNum, reply.fName, &newpath, 1); - CtoPstr(newpath); - error = Create(reply.fName, reply.vRefNum, AMEND_CREATOR, REPO_TYPE); - if (error != 0 && error != dupFNErr) + bile = bile_create(reply.fName, reply.vRefNum, AMEND_CREATOR, + REPO_TYPE); + if (bile == NULL && bile_error(NULL) == dupFNErr) { + FSDelete(reply.fName, reply.vRefNum); + bile = bile_create(reply.fName, reply.vRefNum, AMEND_CREATOR, + REPO_TYPE); + } + if (bile == NULL) err(1, "Failed to create %s: %d", PtoCstr(reply.fName), error); - CreateResFile(newpath); - if (ResError() != 0) - err(1, "Failed to create res file %s: %d", newpath, ResError()); - - free(newpath); - - return repo_init(reply, 1); + return repo_init(bile, 1); } struct repo * -repo_init(SFReply reply, short is_new) +repo_init(struct bile *bile, short is_new) { Str255 buf; + struct bile_object *bob; struct repo *repo; - char *newpath; - Handle resh; - short error, fh, i; + size_t size; + char *data; + short error, fh; + unsigned long i; - getpath(reply.vRefNum, reply.fName, &newpath, 1); - CtoPstr(newpath); - - fh = OpenResFile(newpath); - if (fh == -1) - err(1, "failed to open %s: %d", PtoCstr(newpath), ResError()); - repo = xmalloczero(sizeof(struct repo)); - repo->fh = fh; - repo->vrefnum = reply.vRefNum; + repo->bile = bile; repo->tabwidth = 4; // (short)safe_GetStringAsLong(TABWIDTH_ID); repo->next_file_id = 1; repo->next_commit_id = 1; - memcpy(repo->filename, reply.fName, reply.fName[0] + 1); - PtoCstr(repo->filename); - if (repo_migrate(repo, is_new) != 0) { free(repo); return NULL; } /* fill in file info */ - repo->nfiles = Count1Resources(REPO_FILE_RTYPE); + repo->nfiles = bile_count_by_type(bile, REPO_FILE_RTYPE); if (repo->nfiles) { repo->files = xmalloc(repo->nfiles * sizeof(Ptr)); for (i = 0; i < repo->nfiles; i++) { - resh = GetIndResource(REPO_FILE_RTYPE, i + 1); - if (resh == NULL) - err(1, "failed fetching file %d", i + 1); - repo->files[i] = repo_parse_file(resh); + bob = bile_get_nth_of_type(bile, i, REPO_FILE_RTYPE); + if (bob == NULL) + panic("no %ld file, but count said it should be there", i); + size = bile_read_alloc(bile, REPO_FILE_RTYPE, bob->id, &data); + if (size == 0) + err(1, "failed fetching file %ld", bob->id); + repo->files[i] = repo_parse_file(bob->id, (unsigned char *)data, + size); if (repo->files[i]->id >= repo->next_file_id) repo->next_file_id = repo->files[i]->id + 1; - ReleaseResource(resh); + free(data); } } repo_sort_files(repo); /* fill in commit info */ - repo->ncommits = Count1Resources(REPO_COMMIT_RTYPE); + repo->ncommits = bile_count_by_type(bile, REPO_COMMIT_RTYPE); if (repo->ncommits) { repo->commits = xmalloc(repo->ncommits * sizeof(Ptr)); for (i = 0; i < repo->ncommits; i++) { - resh = GetIndResource(REPO_COMMIT_RTYPE, i + 1); - if (resh == NULL) - err(1, "failed fetching commit %d", i + 1); - repo->commits[i] = repo_parse_commit(resh); + bob = bile_get_nth_of_type(bile, i, REPO_COMMIT_RTYPE); + if (bob == NULL) + panic("no %ld commit, but count said it should be there", + i); + size = bile_read_alloc(bile, REPO_COMMIT_RTYPE, bob->id, + &data); + if (size == 0) + err(1, "failed fetching commit %ld", bob->id); + repo->commits[i] = repo_parse_commit(bob->id, + (unsigned char *)data, size); if (repo->commits[i]->id >= repo->next_commit_id) repo->next_commit_id = repo->commits[i]->id + 1; - ReleaseResource(resh); + free(data); } } repo_sort_commits(repo); @@ -160,7 +169,7 @@ repo_close(struct repo *repo) commit = repo->commits[i]; if (commit == NULL) continue; - + if (commit->log != NULL) DisposHandle(commit->log); @@ -180,27 +189,21 @@ repo_close(struct repo *repo) } free(repo->files); - CloseResFile(repo->vrefnum); + bile_close(repo->bile); free(repo); } struct repo_file * -repo_parse_file(Handle hfile) +repo_parse_file(unsigned long id, unsigned char *data, size_t size) { struct repo_file *file; - short len, i; - unsigned char *data; - short datapos, hlen; - Str255 buf; + unsigned short len, i; + short datapos; - HLock(hfile); - hlen = GetHandleSize(hfile); - data = (unsigned char *)(*hfile); datapos = 0; file = xmalloczero(sizeof(struct repo_file)); - - GetResInfo(hfile, &file->id, &buf, &buf); + file->id = id; /* filename, pstr */ len = data[0]; @@ -228,34 +231,27 @@ repo_parse_file(Handle hfile) ((unsigned long)data[datapos + 3]); datapos += 4; - /* flags, char */ - file->flags = (unsigned char)data[datapos]; + /* flags, unsigned char */ + file->flags = data[datapos]; datapos += 1; - if (datapos != hlen) - err(1, "repo_parse_file handle len %d, data position %d", hlen, + if (datapos != size) + err(1, "repo_parse_file object size %lu, data position %d", size, datapos); - HUnlock(hfile); - return file; } struct repo_commit * -repo_parse_commit(Handle hcommit) +repo_parse_commit(unsigned long id, unsigned char *data, size_t size) { struct repo_commit *commit; - short len, i; - unsigned char *data; - Str255 buf; + unsigned short len, i; + short datapos; - HLock(hcommit); - data = (unsigned char *)(*hcommit); - commit = xmalloczero(sizeof(struct repo_commit)); + commit->id = id; - GetResInfo(hcommit, &commit->id, &buf, &buf); - /* date */ commit->date = ((unsigned long)data[0] << 24) | ((unsigned long)data[1] << 16) | @@ -301,9 +297,9 @@ repo_parse_commit(Handle hcommit) (*(commit->log))[len] = '\0'; HUnlock(commit->log); data += len; + + /* TODO: use datapos and check against size like repo_parse_file */ - HUnlock(hcommit); - return commit; } @@ -358,48 +354,48 @@ void repo_show_diff_text(struct repo *repo, struct repo_commit *commit, TEHandle te) { - Handle diffh; + char truncbuf[64]; + struct bile_object *bob; TextStyle style; + size_t size; + char *dtext; char *buf = NULL; - char truncbuf[64]; unsigned long diff_len, all_len; short header_len, i, blen, height, trunc = 0; unsigned short warn_off; - header_len = repo_diff_header(repo, commit, &buf); - - diffh = Get1Resource(REPO_DIFF_RTYPE, commit->id); - if (diffh == NULL) + bob = bile_find(repo->bile, REPO_DIFF_RTYPE, commit->id); + if (bob == NULL) err(1, "failed finding DIFF %d", commit->id); - diff_len = GetHandleSize(diffh); + diff_len = bob->size; if (diff_len == 0) err(1, "diff zero bytes"); + header_len = repo_diff_header(repo, commit, &buf); + all_len = header_len + diff_len; if (all_len >= MAX_TEXTEDIT_SIZE) { all_len = MAX_TEXTEDIT_SIZE; trunc = 1; } - - DetachResource(diffh); - if (ResError()) - err(1, "Failed detaching diff resource: %d", ResError()); - SetHandleSize(diffh, all_len); - if (MemError()) - err(1, "Failed resizing diff handle to %ul: %d", all_len, - MemError()); - HLock(diffh); - BlockMove(*diffh, *diffh + header_len, all_len - header_len); - memcpy(*diffh, buf, header_len); + + dtext = xmalloc(all_len); + memcpy(dtext, buf, header_len); free(buf); + size = bile_read_object(repo->bile, bob, dtext + header_len, + all_len - header_len); + if (size == 0) + panic("failed reading diff %lu: %d", commit->id, + bile_error(repo->bile)); + if (trunc) { warn_off = MAX_TEXTEDIT_SIZE - header_len - strlen(REPO_DIFF_TOO_BIG); blen = sprintf(truncbuf, REPO_DIFF_TOO_BIG, diff_len - warn_off); - memcpy(*diffh + MAX_TEXTEDIT_SIZE - blen, truncbuf, blen); + memcpy(dtext + MAX_TEXTEDIT_SIZE - blen, truncbuf, blen); } TESetText("", 0, te); @@ -410,9 +406,8 @@ repo_show_diff_text(struct repo *repo, struct repo_com style.tsFont = monaco; style.tsSize = 9; TESetStyle(doFont | doSize, &style, false, te); - /* TODO: can we get away with just replacing te->hText with diffh? */ - TEStylInsert(*diffh, all_len, 0, te); - DisposeHandle(diffh); + TEStylInsert(dtext, all_len, 0, te); + free(dtext); } struct repo_file * @@ -420,39 +415,35 @@ repo_add_file(struct repo *repo) { Point pt = { 75, 100 }; SFReply reply; - Str255 repofname; + Str255 repofname, repopath, newpath; Handle new_fileh; struct repo_file *file; struct repo_file_attrs attrs; unsigned long zero; - char *repopath = NULL, *newpath = NULL, *data; + char *data; short i; SFGetFile(pt, "\p", NULL, -1, 0, NULL, &reply); if (!reply.good) return NULL; - memcpy(repofname, repo->filename, strlen(repo->filename) + 1); - CtoPstr(&repofname); + memcpy(repofname, repo->bile->filename, sizeof(repofname)); /* if the file is not in the same dir as the repo, bail */ - getpath(repo->vrefnum, repofname, &repopath, false); - if (repopath == NULL) - err(1, "Can't find path to repo"); + getpath(repo->bile->vrefnum, repofname, &repopath, false); + if (repopath[0] == 0) + panic("Can't find path to repo"); getpath(reply.vRefNum, reply.fName, &newpath, false); - if (newpath == NULL) - err(1, "Can't find path to new file"); + if (newpath[0] == 0) + panic("Can't find path to new file"); - if (strcmp(repopath, newpath) != 0) { + PtoCstr(repopath); + PtoCstr(newpath); + if (strcmp((char *)&repopath, (char *)&newpath) != 0) { warn("Can't add files from a directory other than the repo's"); - free(newpath); - free(repopath); return NULL; } - free(repopath); - free(newpath); - /* make sure the file isn't already in the repo */ PtoCstr(reply.fName); for (i = 0; i < repo->nfiles; i++) { @@ -485,12 +476,12 @@ short repo_file_update(struct repo *repo, struct repo_file *file) { struct repo_file_attrs attrs; - Str255 filename = { 0 }; - Handle fileh; + Str255 filename; + size_t size, datapos; short error, len, new = 0; - char *data; + unsigned char *data; - memcpy(filename, file->filename, strlen(file->filename)); + strlcpy((char *)filename, file->filename, sizeof(filename)); CtoPstr(filename); error = repo_get_file_attrs(repo, filename, &attrs); @@ -513,45 +504,34 @@ repo_file_update(struct repo *repo, struct repo_file * /* filename len, filename, type, creator, ctime, mtime, flags */ len = 1 + filename[0] + 4 + 4 + 4 + 4 + 1; - fileh = Get1Resource(REPO_FILE_RTYPE, file->id); - if (fileh == NULL) { - /* build a new AFIL resource */ - fileh = xNewHandle(len); - new = 1; - } else if (len != GetHandleSize(fileh)) - warn("repo_file_update len %d vs resource size %d", len, - GetHandleSize(fileh)); - - HLock(fileh); + data = xmalloczero(len); + datapos = 0; - data = (char *)(*fileh); - memset(data, 0, len); - /* copy filename as pstr */ memcpy(data, filename, filename[0] + 1); - data += filename[0] + 1; + datapos += filename[0] + 1; /* file type, creator, and dates */ - memcpy(data, &file->type, 4); - data += 4; - memcpy(data, &file->creator, 4); - data += 4; - memcpy(data, &file->ctime, 4); - data += 4; - memcpy(data, &file->mtime, 4); - data += 4; - memcpy(data, &file->flags, 1); - data += 1; + memcpy(data + datapos, &file->type, 4); + datapos += 4; + memcpy(data + datapos, &file->creator, 4); + datapos += 4; + memcpy(data + datapos, &file->ctime, 4); + datapos += 4; + memcpy(data + datapos, &file->mtime, 4); + datapos += 4; + memcpy(data + datapos, &file->flags, 1); + datapos += 1; - HUnlock(fileh); + if (datapos != len) + err(1, "repo_file_update: datapos %lu, expected %d", datapos, len); - if (new) - AddResource(fileh, REPO_FILE_RTYPE, file->id, filename); - else - ChangedResource(fileh); - - WriteResource(fileh); - ReleaseResource(fileh); + size = bile_write(repo->bile, REPO_FILE_RTYPE, file->id, data, datapos); + if (size != datapos) + panic("repo_file_update: failed writing file data: %d", + bile_error(repo->bile)); + + free(data); } short @@ -561,19 +541,18 @@ repo_get_file_attrs(struct repo *repo, Str255 filename FInfo fi; short error; struct stat sb; - char *filepath = NULL; + Str255 filepath; /* lookup file type and creator */ - error = GetFInfo(filename, repo->vrefnum, &fi); + error = GetFInfo(filename, repo->bile->vrefnum, &fi); if (error != 0) return error; memcpy(&attrs->type, &fi.fdType, 4); memcpy(&attrs->creator, &fi.fdCreator, 4); - getpath(repo->vrefnum, filename, &filepath, true); - error = stat(filepath, &sb); - free(filepath); + getpath(repo->bile->vrefnum, filename, &filepath, true); + error = FStat(filepath, &sb); if (error) { warn("Failed to stat %s", filepath); return -1; @@ -589,12 +568,13 @@ short repo_checkout_file(struct repo *repo, struct repo_file *file, short vrefnum, Str255 filename) { - Handle texth; - size_t len; + struct bile_object *textob; + size_t size, chunk; short error, frefnum; + char *text; - texth = Get1Resource(REPO_TEXT_RTYPE, file->id); - if (texth == NULL) { + textob = bile_find(repo->bile, REPO_TEXT_RTYPE, file->id); + if (textob == NULL) { warn("No copy of file %s exists in repo", file->filename); return -1; } @@ -603,6 +583,7 @@ repo_checkout_file(struct repo *repo, struct repo_file if (error && error != dupFNErr) { warn("Failed to create file %s: %d", PtoCstr(filename), error); + free(textob); return -1; } @@ -612,16 +593,21 @@ repo_checkout_file(struct repo *repo, struct repo_file error = SetEOF(frefnum, 0); if (error) - err(1, "Failed to truncate file %s: %d", PtoCstr(filename), - error); + panic("Failed to truncate file %s: %d", PtoCstr(filename), error); - len = GetHandleSize(texth); - HLock(texth); - error = FSWrite(frefnum, &len, *texth); - if (error) - err(1, "Failed to write file to %s: %d", PtoCstr(filename), error); - ReleaseResource(texth); + /* TODO: add offset to bile_read to read in chunks */ + text = xmalloc(textob->size); + size = bile_read_object(repo->bile, textob, text, textob->size); + if (size != textob->size) + panic("Failed to read text object %ld: %d", textob->id, + bile_error(repo->bile)); + error = FSWrite(frefnum, &size, text); + if (error) + panic("Failed to write file to %s: %d", PtoCstr(filename), error); + + free(text); + free(textob); FSClose(frefnum); return 0; @@ -666,11 +652,12 @@ repo_sort_commits(struct repo *repo) short repo_diff_file(struct repo *repo, struct repo_file *file) { - Handle texth; Str255 fromfilename = { 0 }, tofilename = { 0 }; + Str255 fromfilepath = { 0 }, tofilepath = { 0 }; struct repo_file_attrs attrs; - char *fromfilepath, *tofilepath; + size_t size; char label0[255], label1[255]; + char *text; long len; short error, ret, frefnum, tofile_empty = 0; @@ -679,12 +666,13 @@ repo_diff_file(struct repo *repo, struct repo_file *fi PROGRAM_NAME); CtoPstr(fromfilename); - error = Create(fromfilename, repo->vrefnum, file->creator, file->type); + error = Create(fromfilename, repo->bile->vrefnum, file->creator, + file->type); if (error && error != dupFNErr) err(1, "Failed to create file %s: %d", PtoCstr(fromfilename), error); - error = FSOpen(fromfilename, repo->vrefnum, &frefnum); + error = FSOpen(fromfilename, repo->bile->vrefnum, &frefnum); if (error) err(1, "Failed to open file %s: %d", PtoCstr(fromfilename), error); @@ -693,25 +681,24 @@ repo_diff_file(struct repo *repo, struct repo_file *fi err(1, "Failed to truncate file %s: %d", PtoCstr(fromfilename), error); - getpath(repo->vrefnum, fromfilename, &fromfilepath, true); + getpath(repo->bile->vrefnum, fromfilename, &fromfilepath, true); /* if there's no existing TEXT resource, it's a new file */ - texth = Get1Resource(REPO_TEXT_RTYPE, file->id); - if (texth != NULL) { - len = GetHandleSize(texth); - HLock(texth); - error = FSWrite(frefnum, &len, *texth); + + size = bile_read_alloc(repo->bile, REPO_TEXT_RTYPE, file->id, &text); + if (size > 0) { + error = FSWrite(frefnum, &size, text); if (error) err(1, "Failed to write old file to %s: %d", PtoCstr(fromfilename), error); - ReleaseResource(texth); + free(text); } FSClose(frefnum); memcpy((char *)tofilename, file->filename, sizeof(file->filename)); CtoPstr(tofilename); - getpath(repo->vrefnum, tofilename, &tofilepath, true); + getpath(repo->bile->vrefnum, tofilename, &tofilepath, true); error = repo_get_file_attrs(repo, tofilename, &attrs); if (error == fnfErr) { @@ -720,13 +707,13 @@ repo_diff_file(struct repo *repo, struct repo_file *fi PROGRAM_NAME); CtoPstr(tofilename); - error = Create(tofilename, repo->vrefnum, file->creator, + error = Create(tofilename, repo->bile->vrefnum, file->creator, file->type); if (error && error != dupFNErr) err(1, "Failed to create file %s: %d", PtoCstr(tofilename), error); - getpath(repo->vrefnum, tofilename, &tofilepath, true); + getpath(repo->bile->vrefnum, tofilename, &tofilepath, true); tofile_empty = 1; } else if (error) err(1, "Failed to get info for %s", PtoCstr(tofilename)); @@ -743,26 +730,23 @@ repo_diff_file(struct repo *repo, struct repo_file *fi label0[strlen(label0) - 1] = '\0'; label1[strlen(label1) - 1] = '\0'; - ret = diffreg(fromfilepath, tofilepath, D_PROTOTYPE); + PtoCstr(fromfilepath); + PtoCstr(tofilepath); + ret = diffreg((char *)fromfilepath, (char *)tofilepath, D_PROTOTYPE); /* delete temp file */ - error = FSDelete(fromfilename, repo->vrefnum); + error = FSDelete(fromfilename, repo->bile->vrefnum); if (error) err(1, "Failed to delete temp file %s: %d", PtoCstr(fromfilename), error); if (tofile_empty) { - error = FSDelete(tofilename, repo->vrefnum); + error = FSDelete(tofilename, repo->bile->vrefnum); if (error) err(1, "Failed to delete temp file %s: %d", PtoCstr(tofilename), error); } - if (fromfilepath) - free(fromfilepath); - if (tofilepath) - free(tofilepath); - if (ret == D_SAME) return 0; @@ -772,31 +756,25 @@ repo_diff_file(struct repo *repo, struct repo_file *fi short repo_file_changed(struct repo *repo, struct repo_file *file) { - Handle texth; - Str255 filename = { 0 }; + Str255 filename, filepath; + struct bile_object *bob; struct stat sb; - char *filepath; long fsize; /* if there's no existing TEXT resource, it's a new file */ - texth = Get1Resource(REPO_TEXT_RTYPE, file->id); - if (texth == NULL) { - ReleaseResource(texth); + bob = bile_find(repo->bile, REPO_TEXT_RTYPE, file->id); + if (bob == NULL) return 1; - } - fsize = GetHandleSize(texth); + fsize = bob->size; + free(bob); memcpy((char *)filename, file->filename, sizeof(file->filename)); CtoPstr(filename); - getpath(repo->vrefnum, filename, &filepath, true); + getpath(repo->bile->vrefnum, filename, &filepath, true); - if (stat(filepath, &sb) != 0) { - free(filepath); + if (FStat(filepath, &sb) != 0) return 1; - } - free(filepath); - if (sb.st_size != fsize) return 1; if (sb.st_ctime != file->ctime) @@ -811,13 +789,13 @@ void repo_export_patch(struct repo *repo, struct repo_commit *commit, short vrefnum, Str255 filename) { - Handle diffh; - size_t len; + struct bile_object *bob; + size_t size; char *buf = NULL; short error, frefnum, header_len; - diffh = Get1Resource(REPO_DIFF_RTYPE, commit->id); - if (diffh == NULL) + bob = bile_find(repo->bile, REPO_DIFF_RTYPE, commit->id); + if (bob == NULL) err(1, "failed finding DIFF %d", commit->id); /* @@ -840,20 +818,21 @@ repo_export_patch(struct repo *repo, struct repo_commi err(1, "Failed to truncate file %s: %d", PtoCstr(filename), error); - len = repo_diff_header(repo, commit, &buf); - error = FSWrite(frefnum, &len, buf); + size = repo_diff_header(repo, commit, &buf); + error = FSWrite(frefnum, &size, buf); if (error) err(1, "Failed to write diff header to %s: %d", PtoCstr(filename), error); free(buf); - len = GetHandleSize(diffh); - HLock(diffh); - error = FSWrite(frefnum, &len, *diffh); + buf = xmalloc(bob->size); + size = bile_read_object(repo->bile, bob, buf, bob->size); + error = FSWrite(frefnum, &size, buf); if (error) err(1, "Failed to write diff to %s: %d", PtoCstr(filename), error); - ReleaseResource(diffh); - + + free(buf); + free(bob); FSClose(frefnum); } @@ -864,8 +843,9 @@ repo_commit(struct repo *repo, short *files, short nfi { Str255 tfilename; struct repo_file *file; - Handle commith, texth, fileh; + unsigned char *commit, *tdata, *fdata; FInfo finfo; + size_t size; short commit_len, pos = 0, len; time_t date; long fsize; @@ -889,36 +869,35 @@ repo_commit(struct repo *repo, short *files, short nfi /* log (wstr) */ commit_len += sizeof(short) + loglen; - commith = xNewHandle(commit_len); - HLock(commith); + commit = xmalloc(commit_len); date = Time; - (*commith)[pos++] = (date >> 24) & 0xff; - (*commith)[pos++] = (date >> 16) & 0xff; - (*commith)[pos++] = (date >> 8) & 0xff; - (*commith)[pos++] = date & 0xff; + commit[pos++] = (date >> 24) & 0xff; + commit[pos++] = (date >> 16) & 0xff; + commit[pos++] = (date >> 8) & 0xff; + commit[pos++] = date & 0xff; - (*commith)[pos++] = strlen(author); + commit[pos++] = strlen(author); for (i = 0; i < strlen(author); i++) - (*commith)[pos++] = author[i]; + commit[pos++] = author[i]; - (*commith)[pos++] = (nfiles >> 8) & 0xff; - (*commith)[pos++] = nfiles & 0xff; + commit[pos++] = (nfiles >> 8) & 0xff; + commit[pos++] = nfiles & 0xff; for (i = 0; i < nfiles; i++) { - (*commith)[pos++] = (files[i] >> 8) & 0xff; - (*commith)[pos++] = files[i] & 0xff; + commit[pos++] = (files[i] >> 8) & 0xff; + commit[pos++] = files[i] & 0xff; } - (*commith)[pos++] = (adds >> 8) & 0xff; - (*commith)[pos++] = adds & 0xff; + commit[pos++] = (adds >> 8) & 0xff; + commit[pos++] = adds & 0xff; - (*commith)[pos++] = (subs >> 8) & 0xff; - (*commith)[pos++] = subs & 0xff; + commit[pos++] = (subs >> 8) & 0xff; + commit[pos++] = subs & 0xff; HLock(log); - (*commith)[pos++] = (loglen >> 8) & 0xff; - (*commith)[pos++] = loglen & 0xff; - memcpy(*commith + pos, *log, loglen); + commit[pos++] = (loglen >> 8) & 0xff; + commit[pos++] = loglen & 0xff; + memcpy(commit + pos, *log, loglen); pos += loglen; HUnlock(log); @@ -929,65 +908,61 @@ repo_commit(struct repo *repo, short *files, short nfi commit_id = repo->next_commit_id; /* store diff */ - AddResource(diff, REPO_DIFF_RTYPE, commit_id, "\p"); - if (ResError()) - err(1, "Failed storing diff in repo file (%d)", ResError()); - WriteResource(diff); - ReleaseResource(diff); - - /* store commit */ - AddResource(commith, REPO_COMMIT_RTYPE, commit_id, "\p"); - if (ResError()) - err(1, "Failed storing commit in repo file (%d)", ResError()); - WriteResource(commith); + HLock(diff); + size = bile_write(repo->bile, REPO_DIFF_RTYPE, commit_id, *diff, + difflen); + if (size != difflen) + panic("Failed storing diff in repo file: %d", + bile_error(repo->bile)); + HUnlock(diff); + /* store commit */ + size = bile_write(repo->bile, REPO_COMMIT_RTYPE, commit_id, commit, + commit_len); + if (size != commit_len) + panic("Failed storing commit in repo file: %d", + bile_error(repo->bile)); + /* used later, don't free yet */ + /* store new versions of each file */ for (i = 0; i < nfiles; i++) { file = repo_file_with_id(repo, files[i]); if (file == NULL) - err(1, "Bogus file %d in commit", files[i]); + panic("Bogus file %d in commit", files[i]); - len = strlen(file->filename); - memcpy(tfilename, file->filename, len); - tfilename[len] = '\0'; + strlcpy((char *)tfilename, file->filename, sizeof(tfilename)); CtoPstr(tfilename); /* update file contents if file wasn't deleted */ - error = GetFInfo(tfilename, repo->vrefnum, &finfo); + error = GetFInfo(tfilename, repo->bile->vrefnum, &finfo); if (error && error != fnfErr) - err(1, "Error getting file info for %s", PtoCstr(tfilename)); + panic("Error getting file info for %s", PtoCstr(tfilename)); - SetResLoad(false); - texth = Get1Resource(REPO_TEXT_RTYPE, file->id); - if (texth != NULL) { - RmveResource(texth); - ReleaseResource(texth); - } - SetResLoad(true); - if (error != fnfErr) { - error = FSOpen(tfilename, repo->vrefnum, &frefnum); + error = FSOpen(tfilename, repo->bile->vrefnum, &frefnum); if (error) - err(1, "Failed to open file %s: %d", PtoCstr(tfilename), + panic("Failed to open file %s: %d", PtoCstr(tfilename), error); error = GetEOF(frefnum, &fsize); if (error) - err(1, "Failed to get size of file %s: %d", + panic("Failed to get size of file %s: %d", PtoCstr(tfilename), error); - texth = xNewHandle(fsize); - HLock(texth); - error = FSRead(frefnum, &fsize, *texth); + tdata = xmalloc(fsize); + error = FSRead(frefnum, &fsize, tdata); if (error) - err(1, "Failed to read %ul of file %s: %d", fsize, + panic("Failed to read %ul of file %s: %d", fsize, PtoCstr(tfilename), error); FSClose(frefnum); - AddResource(texth, REPO_TEXT_RTYPE, files[i], tfilename); - WriteResource(texth); - ReleaseResource(texth); + size = bile_write(repo->bile, REPO_TEXT_RTYPE, files[i], tdata, + fsize); + if (size != fsize) + panic("Failed to write new text file at %s: %d", + PtoCstr(tfilename), bile_error(repo->bile)); + free(tdata); } repo_file_update(repo, file); @@ -998,35 +973,31 @@ repo_commit(struct repo *repo, short *files, short nfi /* update commit list */ repo->ncommits++; repo->commits = xrealloc(repo->commits, repo->ncommits * sizeof(Ptr)); - repo->commits[repo->ncommits - 1] = repo_parse_commit(commith); + repo->commits[repo->ncommits - 1] = repo_parse_commit(commit_id, + commit, commit_len); - ReleaseResource(commith); + free(commit); repo_sort_commits(repo); - - UpdateResFile(repo->fh); - - if (FlushVol(nil, repo->vrefnum)) - warn("Failed flushing filesystem after committing, " - "proceed with caution"); } short repo_migrate(struct repo *repo, short is_new) { - Handle verh, resh; - short ver, add = 0, i, nfiles, size; - + struct bile_object *bob; + Str255 tname; + Handle h; + size_t size; + unsigned long id; + OSType type, tmpltype; + short add = 0, i, nfiles, ntmpls; + char ver; + if (is_new) ver = REPO_CUR_VERS; else { - verh = Get1Resource(REPO_VERS_RTYPE, 1); - if (verh == NULL) + if (bile_read(repo->bile, REPO_VERS_RTYPE, 1, &ver, 1) != 1) ver = 1; - else { - ver = (unsigned char)((*verh)[0]); - ReleaseResource(verh); - } if (ver == REPO_CUR_VERS) return 0; @@ -1036,89 +1007,87 @@ repo_migrate(struct repo *repo, short is_new) return -1; } - if (!is_new) + if (!is_new) { + progress("Backing up repo..."); repo_backup(repo); + } /* per-version migrations */ - if (ver == 1) { - /* version 1 had no file flags */ - nfiles = Count1Resources(REPO_FILE_RTYPE); - for (i = 1; i <= nfiles; i++) { - resh = GetIndResource(REPO_FILE_RTYPE, i); - if (resh == NULL) - err(1, "failed fetching file %d", i); - size = GetHandleSize(resh); - ReallocHandle(resh, size + 1); - if (MemError()) - err(1, "Out of memory allocating new handle of size %ld", - size + 1); - HLock(resh); - (*resh)[size] = 0; - HUnlock(resh); - ChangedResource(resh); - WriteResource(resh); - ReleaseResource(resh); - } - ver = 2; - } + + /* 1 had no version number :( */ + /* 1->2 added a version */ + /* 2->3 was switching from resource forks to bile */ /* store new version */ - verh = Get1Resource(REPO_VERS_RTYPE, 1); - if (verh == NULL) { - verh = NewHandle(1); - add = 1; + ver = REPO_CUR_VERS; + if (bile_write(repo->bile, REPO_VERS_RTYPE, 1, &ver, 1) != 1) + panic("Failed writing new version: %d", bile_error(repo->bile)); + + bile_fsck(repo->bile); + + progress("Copying templates..."); + + /* copy templates from our resource file to bile file */ + while ((bob = bile_get_nth_of_type(repo->bile, 0, 'TMPL')) != NULL) { + bile_delete(repo->bile, 'TMPL', bob->id); + free(bob); } - (*verh)[0] = ver; - if (add) - AddResource(verh, REPO_VERS_RTYPE, 1, "\p"); - else - ChangedResource(verh); - /* update templates */ + ntmpls = Count1Resources('TMPL'); for (i = 0; i < ntmpls; i++) { - resh = Get1Resource(tmpls[i].type, tmpls[i].id); - if (resh) - RmveResource(resh); - AddResource(tmpls[i].h, tmpls[i].type, tmpls[i].id, tmpls[i].name); - WriteResource(tmpls[i].h); - DetachResource(tmpls[i].h); + h = GetIndResource('TMPL', i + 1); + if (h == NULL) + err(1, "Failed fetching TMPL %d", i + 1); + GetResInfo(h, &id, &type, &tname); + + /* + * The template name should be an OSType as a string, use it as + * the id + */ + if (tname[0] != 4) + panic("TMPL %ld has bogus name \"%s\"", id, PtoCstr(tname)); + tmpltype = ((unsigned long)tname[1] << 24) | + ((unsigned long)tname[2] << 16) | + ((unsigned long)tname[3] << 8) | + ((unsigned long)tname[4]); + size = bile_write(repo->bile, 'TMPL', tmpltype, *h, + GetHandleSize(h)); + if (size != GetHandleSize(h)) + panic("short write saving TMPL %ld: %d", id, + bile_error(repo->bile)); + + DetachResource(h); } - UpdateResFile(repo->fh); - + progress("Doing a full check of the new repo..."); + bile_fsck(repo->bile); + + progress(NULL); + return 0; } void repo_backup(struct repo *repo) { - Str255 source_filename, dest_filename; + Str255 repo_filename, source_filename, dest_filename, path; FInfo fi; short error; - char *path = NULL; short source_ref, dest_ref; - sprintf((char *)&source_filename, "%s", repo->filename); - CtoPstr(source_filename); - if (getpath(repo->vrefnum, source_filename, &path, false) != 0) + if (getpath(repo->bile->vrefnum, repo->bile->filename, &path, + false) != 0) err(1, "Failed resolving path of open repo"); + PtoCstr(path); - sprintf((char *)&source_filename, "%s:%s", path, repo->filename); - sprintf((char *)&dest_filename, "%s (backup)", source_filename); + memcpy(repo_filename, repo->bile->filename, sizeof(repo_filename)); + PtoCstr(repo_filename); + sprintf((char *)source_filename, "%s:%s", path, repo_filename); + sprintf((char *)dest_filename, "%s (backup)", source_filename); CtoPstr(source_filename); CtoPstr(dest_filename); - free(path); - /* - * Tell copy_file to keep source open, which is our current resource - * file. Even though it calls OpenRFPerm and is supposed to get a new - * filehandle, it gets the same one as our resource file so closing it - * causes problems for us after copying. - */ - error = copy_file(source_filename, dest_filename, true, true); + error = copy_file(source_filename, dest_filename, true); if (error) err(1, "Failed backing up repo: %d", error); - - if (FlushVol(nil, repo->vrefnum)) - err(1, "Failed flushing filesystem after backup, aborting"); } --- repo.h Thu Dec 30 14:49:23 2021 +++ repo.h Mon Jan 10 20:52:11 2022 @@ -18,6 +18,7 @@ #define __REPO_H__ #include <time.h> +#include "bile.h" #define AMEND_CREATOR 'AMND' @@ -33,7 +34,7 @@ #define REPO_DIFF_TOO_BIG "\r[ Diff too large to view, %lu bytes not shown ]" -#define REPO_CUR_VERS 2 +#define REPO_CUR_VERS 3 struct repo_file { short id; @@ -66,9 +67,7 @@ struct repo_commit { }; struct repo { - char filename[256]; - short fh; - short vrefnum; + struct bile *bile; short tabwidth; short nfiles; struct repo_file **files; @@ -81,8 +80,10 @@ struct repo { struct repo *repo_open(AppFile *file); struct repo *repo_create(void); void repo_close(struct repo *repo); -struct repo_commit *repo_parse_commit(Handle hcommit); -struct repo_file *repo_parse_file(Handle hfile); +struct repo_commit *repo_parse_commit(unsigned long id, unsigned char *data, + size_t size); +struct repo_file * repo_parse_file(unsigned long id, unsigned char *data, + size_t size); struct repo_file *repo_file_with_id(struct repo *repo, short id); void repo_show_diff_text(struct repo *repo, struct repo_commit *commit, TEHandle te);