AmendHub

Download:

jcs

/

amend

/

amendments

/

20

browser+repo: Add diff exporting

Refactor diff header generation into a function to also use here.
 
When disabling menus, only disable their items. This avoids having
to call DrawMenuBar() which flashes annoyingly.

jcs made amendment 20 over 3 years ago
--- amend.h Mon Oct 18 13:09:14 2021 +++ amend.h Wed Oct 27 09:39:20 2021 @@ -35,8 +35,11 @@ #define REPO_MENU_REVERT_FILE_ID 2 #define REPO_MENU_APPLY_DIFF_ID 3 +#define COMMIT_MENU_ID 132 +#define COMMIT_MENU_EXPORT_ID 1 + #define COMMIT_LDEF_ID 128 #define TABWIDTH_ID 130 -extern MenuHandle file_menu, edit_menu, repo_menu; +extern MenuHandle file_menu, edit_menu, repo_menu, commit_menu; --- browser.c Mon Oct 18 13:09:06 2021 +++ browser.c Wed Oct 27 13:43:28 2021 @@ -67,6 +67,11 @@ browser_idle(struct browser *browser) case BROWSER_STATE_REVERT_FILE: browser_revert_file(browser); browser->state = BROWSER_STATE_IDLE; + break; + case BROWSER_STATE_EXPORT_DIFF: + browser_export_diff(browser); + browser->state = BROWSER_STATE_IDLE; + break; } } @@ -160,7 +165,6 @@ browser_init(struct repo *repo) 1, 1, 1, scrollBarProc, 0L); browser_update_menu(browser); - DrawMenuBar(); browser_add_files(browser); UpdateScrollbarForTE(browser->diff_scroller, browser->diff_te, true); ShowWindow(browser->win); @@ -317,15 +321,19 @@ browser_show_commit(struct browser *browser, struct re { struct repo_diff *diff; - if (commit == NULL) + if (commit == NULL) { TESetText("", 0, browser->diff_te); - else { + HLock(browser->diff_te); + InvalRect(&(*(browser->diff_te))->viewRect); + HUnlock(browser->diff_te); + } else { SetCursor(*(GetCursor(watchCursor))); - repo_show_diff_text(commit, browser->diff_te); + repo_show_diff_text(browser->repo, commit, browser->diff_te); SetCursor(&arrow); } UpdateScrollbarForTE(browser->diff_scroller, browser->diff_te, true); + browser_update_menu(browser); } void @@ -360,10 +368,33 @@ browser_revert_file(struct browser *browser) } void +browser_export_diff(struct browser *browser) +{ + Point pt = { 75, 100 }; + Cell selected = { 0 }; + struct repo_commit *commit; + short error, len; + SFReply reply; + + if (LGetSelect(true, &selected, browser->commit_list) == false) + return; + + len = sizeof(Ptr); + LGetCell(&commit, &len, selected, browser->commit_list); + + SFPutFile(pt, "\pSave diff as:", NULL, NULL, &reply); + if (!reply.good) + return; + + repo_export_diff(browser->repo, commit, reply.vRefNum, reply.fName); +} + +void browser_update_menu(struct browser *browser) { size_t vlines; TERec *diff; + Cell cell = { 0, 0 }; HLock(browser->diff_te); diff = *(browser->diff_te); @@ -378,14 +409,21 @@ browser_update_menu(struct browser *browser) else EnableItem(edit_menu, EDIT_MENU_COPY_ID); + HUnlock(browser->diff_te); + if (browser->repo->nfiles == 0) HiliteControl(browser->diff_button, 255); else HiliteControl(browser->diff_button, 0); - HUnlock(browser->diff_te); + EnableItem(repo_menu, REPO_MENU_ADD_FILE_ID); + EnableItem(repo_menu, REPO_MENU_REVERT_FILE_ID); + EnableItem(repo_menu, REPO_MENU_APPLY_DIFF_ID); - EnableItem(repo_menu, 0); + if (LGetSelect(true, &cell, browser->commit_list)) + EnableItem(commit_menu, COMMIT_MENU_EXPORT_ID); + else + DisableItem(commit_menu, COMMIT_MENU_EXPORT_ID); } void --- browser.h Mon Oct 18 13:09:23 2021 +++ browser.h Wed Oct 27 13:05:39 2021 @@ -30,7 +30,8 @@ enum { BROWSER_STATE_OPEN_COMMITTER, BROWSER_STATE_COMMITTER_DO_DIFF, BROWSER_STATE_WAITING_FOR_COMMITTER, - BROWSER_STATE_REVERT_FILE + BROWSER_STATE_REVERT_FILE, + BROWSER_STATE_EXPORT_DIFF }; struct browser { @@ -55,6 +56,7 @@ void browser_update_menu(struct browser *browser); void browser_update(struct browser *browser, EventRecord *event); void browser_show_commit(struct browser *browser, struct repo_commit *commit); +void browser_export_diff(struct browser *browser); short browser_selected_file_ids(struct browser *browser, short **selected_files); void browser_mouse_down(struct browser *browser, EventRecord *event); --- main.c Mon Oct 18 09:22:19 2021 +++ main.c Wed Oct 27 12:58:00 2021 @@ -23,7 +23,7 @@ #include "repo.h" #include "util.h" -MenuHandle file_menu, edit_menu, repo_menu; +MenuHandle file_menu, edit_menu, repo_menu, commit_menu; Handle commit_list_ldef_h; short quitting = 0; struct browser *cur_browser = NULL; @@ -64,7 +64,9 @@ main(void) file_menu = GetMHandle(FILE_MENU_ID); edit_menu = GetMHandle(EDIT_MENU_ID); repo_menu = GetMHandle(REPO_MENU_ID); + commit_menu = GetMHandle(COMMIT_MENU_ID); update_menu(); + DrawMenuBar(); /* dynamically patch list LDEF to point to our *_list_ldef funcs */ commit_list_ldef_h = GetResource('LDEF', COMMIT_LDEF_ID); @@ -259,7 +261,15 @@ handle_menu(long menu_id) break; } break; + case COMMIT_MENU_ID: + switch (LoWord(menu_id)) { + case COMMIT_MENU_EXPORT_ID: + if (cur_browser) + cur_browser->state = BROWSER_STATE_EXPORT_DIFF; + break; } + break; + } HiliteMenu(0); } @@ -274,6 +284,10 @@ update_menu(void) DisableItem(edit_menu, EDIT_MENU_SELECT_ALL_ID); DisableItem(edit_menu, EDIT_MENU_COPY_ID); - DisableItem(repo_menu, 0); - DrawMenuBar(); + + DisableItem(repo_menu, REPO_MENU_ADD_FILE_ID); + DisableItem(repo_menu, REPO_MENU_REVERT_FILE_ID); + DisableItem(repo_menu, REPO_MENU_APPLY_DIFF_ID); + + DisableItem(commit_menu, COMMIT_MENU_EXPORT_ID); } --- repo.c Mon Oct 18 17:12:17 2021 +++ repo.c Wed Oct 27 13:42:15 2021 @@ -29,6 +29,8 @@ void repo_sort_commits(struct repo *repo); short repo_get_file_attrs(struct repo *repo, Str255 filename, struct repo_file_attrs *attrs); short repo_file_update(struct repo *repo, struct repo_file *file); +unsigned short repo_diff_header(struct repo *repo, + struct repo_commit *commit, char **ret); struct repo * repo_open(AppFile *file) @@ -86,7 +88,7 @@ repo_create(void) DetachResource(tmpls[i].h); } - error = Create(reply.fName, reply.vRefNum, REPO_CREATOR, REPO_TYPE); + error = Create(reply.fName, reply.vRefNum, AMEND_CREATOR, REPO_TYPE); if (error != 0) err(1, "Failed to create %s: %d", PtoCstr(reply.fName), error); @@ -328,38 +330,17 @@ repo_file_with_id(struct repo *repo, short id) return NULL; } -void -repo_show_diff_text(struct repo_commit *commit, TEHandle te) +unsigned short +repo_diff_header(struct repo *repo, struct repo_commit *commit, + char **ret) { - Handle diffh; - TextStyle style; struct tm *ttm = NULL; - char *buf; - char truncbuf[64]; - unsigned long diff_len, all_len; - short header_len, i, blen, height, trunc = 0; - unsigned short warn_off; + unsigned short header_len; + short i; - diffh = Get1Resource(REPO_DIFF_RTYPE, commit->id); - if (diffh == NULL) - err(1, "failed finding DIFF %d", commit->id); - - diff_len = GetHandleSize(diffh); - if (diff_len == 0) { - /* - * Not sure why this happens when viewing the diff that was just - * committed. - */ - ReleaseResource(diffh); - diffh = Get1Resource(REPO_DIFF_RTYPE, commit->id); - diff_len = GetHandleSize(diffh); - if (diff_len == 0) - err(1, "diff still zero bytes"); - } - - buf = xmalloc(512); + *ret = xmalloc(128 + commit->log_len); ttm = localtime(&commit->date); - header_len = sprintf(buf, + header_len = sprintf(*ret, "Author: %s\r" "Date: %04d-%02d-%02d %02d:%02d:%02d\r" "\r ", @@ -370,17 +351,42 @@ repo_show_diff_text(struct repo_commit *commit, TEHand /* copy log, indenting each line */ HLock(commit->log); for (i = 0; i < commit->log_len; i++) { - *(buf + header_len++) = (*(commit->log))[i]; + *(*ret + header_len++) = (*(commit->log))[i]; if ((*(commit->log))[i] == '\r' && i < commit->log_len - 1) { - *(buf + header_len++) = ' '; - *(buf + header_len++) = ' '; + *(*ret + header_len++) = ' '; + *(*ret + header_len++) = ' '; } } HUnlock(commit->log); - *(buf + header_len++) = '\r'; - *(buf + header_len++) = '\r'; + *(*ret + header_len++) = '\r'; + *(*ret + header_len++) = '\r'; + return header_len; +} + +void +repo_show_diff_text(struct repo *repo, struct repo_commit *commit, + TEHandle te) +{ + Handle diffh; + TextStyle style; + 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) + err(1, "failed finding DIFF %d", commit->id); + + diff_len = GetHandleSize(diffh); + if (diff_len == 0) + err(1, "diff zero bytes"); + all_len = header_len + diff_len; if (all_len >= MAX_TEXTEDIT_SIZE) { all_len = MAX_TEXTEDIT_SIZE; @@ -738,6 +744,56 @@ repo_diff_file(struct repo *repo, struct repo_file *fi } void +repo_export_diff(struct repo *repo, struct repo_commit *commit, + short vrefnum, Str255 filename) +{ + Handle diffh; + size_t len; + char *buf = NULL; + short error, frefnum, header_len; + + diffh = Get1Resource(REPO_DIFF_RTYPE, commit->id); + if (diffh == NULL) + err(1, "failed finding DIFF %d", commit->id); + + /* + * Don't use our creator here because we don't want finder opening us + * to view diffs, they are plain text + */ + error = Create(filename, vrefnum, DIFF_FILE_TYPE, DIFF_FILE_TYPE); + if (error && error != dupFNErr) { + warn("Failed to create file %s: %d", PtoCstr(filename), + error); + return; + } + + error = FSOpen(filename, vrefnum, &frefnum); + if (error) + err(1, "Failed to open file %s: %d", PtoCstr(filename), error); + + error = SetEOF(frefnum, 0); + if (error) + err(1, "Failed to truncate file %s: %d", PtoCstr(filename), + error); + + len = repo_diff_header(repo, commit, &buf); + error = FSWrite(frefnum, &len, 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); + if (error) + err(1, "Failed to write diff to %s: %d", PtoCstr(filename), error); + ReleaseResource(diffh); + + FSClose(frefnum); +} + +void repo_commit(struct repo *repo, short *files, short nfiles, short adds, short subs, Handle log, short loglen, Handle diff, unsigned long difflen) { @@ -811,6 +867,7 @@ repo_commit(struct repo *repo, short *files, short nfi 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, NULL); --- repo.h Mon Oct 18 15:08:25 2021 +++ repo.h Wed Oct 27 13:42:51 2021 @@ -19,7 +19,8 @@ #include <time.h> -#define REPO_CREATOR 'AMND' +#define AMEND_CREATOR 'AMND' + #define REPO_TYPE 'AMRP' #define REPO_FILE_RTYPE 'AFIL' @@ -27,6 +28,8 @@ #define REPO_DIFF_RTYPE 'DIFF' #define REPO_TEXT_RTYPE 'TEXT' +#define DIFF_FILE_TYPE 'TEXT' + #define REPO_DIFF_TOO_BIG "\r[ Diff too large to view, %lu bytes not shown ]" struct repo_file { @@ -76,10 +79,13 @@ void repo_close(struct repo *repo); struct repo_commit *repo_parse_commit(Handle hcommit); struct repo_file *repo_parse_file(Handle hfile); struct repo_file *repo_file_with_id(struct repo *repo, short id); -void repo_show_diff_text(struct repo_commit *commit, TEHandle te); +void repo_show_diff_text(struct repo *repo, struct repo_commit *commit, + TEHandle te); struct repo_file *repo_add_file(struct repo *repo); short repo_diff_file(struct repo *repo, struct repo_file *file); short repo_checkout_file(struct repo *repo, struct repo_file *file, + short vrefnum, Str255 filename); +void repo_export_diff(struct repo *repo, struct repo_commit *commit, short vrefnum, Str255 filename); void repo_commit(struct repo *repo, short *files, short nfiles, short adds, short subs, Handle log, short loglen, Handle diff, unsigned long difflen);