diff --git a/SYNCING.md b/SYNCING.md index 9b710a463..a4673dac0 100644 --- a/SYNCING.md +++ b/SYNCING.md @@ -35,7 +35,7 @@ The usual local layout is: ```sh cd /some/where/useful git clone https://github.com/tmux/tmux.git tmux-portable -git clone https://github.com/ThomasAdam/tmux-obsd.git tmux-openbsd-cutover +git clone https://github.com/tmux/tmux-openbsd-cutover.git tmux-openbsd-cutover ``` The exact directory names do not matter, but the examples below use: @@ -56,18 +56,19 @@ The cutover repository has three important branches: # Adding the OpenBSD remote to portable -In the portable repository, add the cutover repository as a remote: +In the portable repository, add the published cutover repository as a remote. +This works regardless of which branch is checked out in a local cutover clone: ```sh cd /path/to/tmux-portable -git remote add tmux-openbsd /path/to/tmux-openbsd-cutover +git remote add tmux-openbsd https://github.com/tmux/tmux-openbsd-cutover.git git config remote.tmux-openbsd.tagOpt --no-tags ``` If the remote already exists, update it instead: ```sh -git remote set-url tmux-openbsd /path/to/tmux-openbsd-cutover +git remote set-url tmux-openbsd https://github.com/tmux/tmux-openbsd-cutover.git git config remote.tmux-openbsd.tagOpt --no-tags ``` @@ -77,6 +78,32 @@ Fetch the cutover master branch explicitly: git fetch --no-tags tmux-openbsd master:refs/remotes/tmux-openbsd/master ``` +To merge unpublished changes from a local cutover clone instead, first ensure +it has an up-to-date local `master` branch. A normal clone may check out +`automation` and have only `origin/master`; fetching `master` from that clone +will then fail with `couldn't find remote ref master`. + +With a clean cutover working tree: + +```sh +cd /path/to/tmux-openbsd-cutover +git fetch --no-tags origin +git switch master +git merge --ff-only origin/master +``` + +`git switch master` creates a tracking branch from `origin/master` if there is +no local `master` yet. If the fast-forward fails, reconcile the local cutover +changes before continuing; do not reset them away. + +Then, in portable, point the remote at that clone and fetch its local `master`: + +```sh +cd /path/to/tmux-portable +git remote set-url tmux-openbsd /path/to/tmux-openbsd-cutover +git fetch --no-tags tmux-openbsd master:refs/remotes/tmux-openbsd/master +``` + # Automated syncing The normal sync is performed by the GitHub Actions workflow in the @@ -99,7 +126,9 @@ OpenBSD changes. If the workflow fails while merging into portable, do the merge locally and push the result. -Start from an up-to-date portable master: +Start with a clean working tree and an up-to-date portable master. If a merge +is already in progress, skip to resolving conflicts, or abort it before +starting again: ```sh cd /path/to/tmux-portable @@ -108,10 +137,15 @@ git checkout master git pull --ff-only origin master ``` -Fetch the cutover branch: +Fetch the published cutover branch. Update an existing remote as well, since +it may point at a local clone without a `master` branch or with a stale one: ```sh -git remote add tmux-openbsd /path/to/tmux-openbsd-cutover 2>/dev/null || true +if git remote get-url tmux-openbsd >/dev/null 2>&1; then + git remote set-url tmux-openbsd https://github.com/tmux/tmux-openbsd-cutover.git +else + git remote add tmux-openbsd https://github.com/tmux/tmux-openbsd-cutover.git +fi git config remote.tmux-openbsd.tagOpt --no-tags git fetch --no-tags tmux-openbsd master:refs/remotes/tmux-openbsd/master ``` @@ -122,7 +156,22 @@ Merge it: git merge --no-ff --log refs/remotes/tmux-openbsd/master ``` -Resolve conflicts by deciding whether portable or OpenBSD owns the file. +If merging a local cutover branch instead, use the local-clone preparation +and fetch commands above in place of this fetch block. + +When the merge reports conflicts, it leaves the merge in progress. List the +unresolved files, edit the conflict markers to combine the required portable +and OpenBSD changes, then stage each resolved file: + +```sh +git diff --name-only --diff-filter=U +git diff -- path/to/file +git add path/to/file +``` + +For files that should come entirely from one side, decide whether portable or +OpenBSD owns the file before using the commands below. They replace the whole +file, including changes outside the conflicting hunks. Useful commands: @@ -140,11 +189,25 @@ git add path/to/file This takes the OpenBSD/cutover version of a conflicted file. +For a modify/delete conflict, the side that deleted the file has no version +to check out. For example, portable generates `Makefile` using autotools and +does not track OpenBSD's `Makefile`. If Git reports that `Makefile` was deleted +in HEAD and modified in cutover, keep the portable deletion with: + +```sh +git rm -- Makefile +``` + +This removes the OpenBSD file left by the merge; regenerate the portable +`Makefile` with your usual configure command before building. Use this only +for the unmerged OpenBSD file, not an existing generated build file. + Before committing, inspect the result: ```sh git status git diff --check +git diff --cached --check git diff --cached --stat ``` diff --git a/cmd-run-shell.c b/cmd-run-shell.c index 485dca765..4834cd9f7 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-run-shell.c,v 1.94 2026/08/25 06:04:33 nicm Exp $ */ +/* $OpenBSD: cmd-run-shell.c,v 1.95 2026/09/20 07:59:55 nicm Exp $ */ /* * Copyright (c) 2009 Tiago Cunha @@ -163,11 +163,9 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item) } if (cdata->client != NULL) cdata->client->references++; - if (args_has(args, 'c')) { - ft = format_create_from_target(item); - cdata->cwd = format_expand(ft, args_get(args, 'c')); - format_free(ft); - } else + if (args_has(args, 'c')) + cdata->cwd = format_single_from_target(item, args_get(args, 'c')); + else cdata->cwd = xstrdup(server_client_get_cwd(c, s)); if (args_has(args, 'E')) diff --git a/format.c b/format.c index 19f1baa86..23cde4852 100644 --- a/format.c +++ b/format.c @@ -1,4 +1,4 @@ -/* $OpenBSD: format.c,v 1.417 2026/09/08 15:42:26 nicm Exp $ */ +/* $OpenBSD: format.c,v 1.418 2026/09/20 08:19:31 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott diff --git a/layout-custom.c b/layout-custom.c index afe399cd0..83e0f9cb4 100644 --- a/layout-custom.c +++ b/layout-custom.c @@ -1,4 +1,4 @@ -/* $OpenBSD: layout-custom.c,v 1.41 2026/09/09 09:01:19 nicm Exp $ */ +/* $OpenBSD: layout-custom.c,v 1.42 2026/09/20 08:37:47 nicm Exp $ */ /* * Copyright (c) 2010 Nicholas Marriott @@ -283,26 +283,28 @@ layout_checksum(const char *layout) char * layout_dump(__unused struct window *w, struct layout_cell *lcroot, int flags) { - struct layout_string layout_string; - char *out = NULL; + struct layout_string layout_string = { 0 }; + char *out; if (lcroot == NULL) - return NULL; - + goto bad; layout_string_init(&layout_string); - - if (layout_append(lcroot, &layout_string, flags) == 0) { - if (flags & LAYOUT_CUSTOM_OLD_FORMAT) - xasprintf(&out, "%04hx,%s", - layout_checksum(layout_string.dat), - layout_string.dat); - else - xasprintf(&out, "{\"V\":2,\"L\":%s}", - layout_string.dat); + if (layout_append(lcroot, &layout_string, flags) != 0) + goto bad; + if (~flags & LAYOUT_CUSTOM_OLD_FORMAT) + xasprintf(&out, "{\"V\":2,\"L\":%s}", layout_string.dat); + else { + xasprintf(&out, "%04hx,%s", layout_checksum(layout_string.dat), + layout_string.dat); } layout_string_free(&layout_string); - return (out); + +bad: + layout_string_free(&layout_string); + if (~flags & LAYOUT_CUSTOM_OLD_FORMAT) + return (NULL); + return (xstrdup("0000,")); } /* Append information for a single cell in a JSON (v2) format. */ diff --git a/layout.c b/layout.c index a67f62a99..203dcb663 100644 --- a/layout.c +++ b/layout.c @@ -1,4 +1,4 @@ -/* $OpenBSD: layout.c,v 1.100 2026/09/11 08:16:14 nicm Exp $ */ +/* $OpenBSD: layout.c,v 1.101 2026/09/20 08:42:46 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -1730,7 +1730,7 @@ layout_floating_args_parse(struct cmdq_item *item, struct args *args, enum pane_lines lines, struct window *w, struct layout_geometry *lg, char **cause) { - int sx, sy, ox, oy; + int sx, sy, ox, oy, pad; char *error = NULL; sx = lg->sx == UINT_MAX ? w->sx / 2 : lg->sx; @@ -1779,12 +1779,20 @@ layout_floating_args_parse(struct cmdq_item *item, struct args *args, } } + if (!window_has_floating_panes(w)) { + w->last_new_pane_x = 0; + w->last_new_pane_y = 0; + } if (ox == INT_MAX) { if (w->last_new_pane_x == 0) ox = 4; else { + if (lines != PANE_LINES_NONE) + pad = 1; + else + pad = 0; ox = w->last_new_pane_x + 4; - if (w->last_new_pane_x > w->sx) + if (ox + sx + pad > (int)w->sx) ox = 4; } w->last_new_pane_x = ox; @@ -1795,8 +1803,12 @@ layout_floating_args_parse(struct cmdq_item *item, struct args *args, if (w->last_new_pane_y == 0) oy = 2; else { + if (lines != PANE_LINES_NONE) + pad = 1; + else + pad = 0; oy = w->last_new_pane_y + 2; - if (w->last_new_pane_y > w->sy) + if (oy + sy + pad > (int)w->sy) oy = 2; } w->last_new_pane_y = oy; diff --git a/utf8.c b/utf8.c index e3da33a60..9d15b7a1a 100644 --- a/utf8.c +++ b/utf8.c @@ -1,4 +1,4 @@ -/* $OpenBSD: utf8.c,v 1.72 2026/09/01 12:49:49 nicm Exp $ */ +/* $OpenBSD: utf8.c,v 1.73 2026/09/20 08:11:00 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott diff --git a/window.c b/window.c index 716d5fd99..e98512783 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window.c,v 1.374 2026/09/08 08:37:56 nicm Exp $ */ +/* $OpenBSD: window.c,v 1.375 2026/09/20 07:35:06 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -450,20 +450,17 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel) static void window_destroy(struct window *w) { + struct window_pane *wp; + log_debug("window @%u destroyed (%d references)", w->id, w->references); - /* - * Pin the window while unzooming: layout_fix_panes() resizes panes, - * which fires the pane-resized hook, and its event payload takes and - * drops its own reference on the window. references is already 0 - * here, so that reference reaching 0 again would call window_destroy() - * a second time from inside this call, freeing w (and its panes) - * out from under the rest of this function. - */ - w->references++; - window_unzoom(w, 0); - w->references--; - + if (w->flags & WINDOW_ZOOMED) { + w->flags &= ~WINDOW_ZOOMED; + TAILQ_FOREACH(wp, &w->panes, entry) { + wp->flags &= ~PANE_ZOOMED; + wp->saved_layout_cell = NULL; + } + } RB_REMOVE(windows, &windows, w); layout_free_cell(w->layout_root, 0);