fix(mkrep): make origin linking idempotent #155
@@ -0,0 +1,53 @@
|
|||||||
|
# Copyright (C) 2026 Rootiest
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
# DEPENDENCIES
|
||||||
|
# _mkrep_say, __fish_palette, git
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
# _mkrep_add_origin <silent> <url>
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
# Links origin to <url>, idempotently, for mkrep's --remote and --server
|
||||||
|
# link-existing flows. Both can run against a directory that is already a
|
||||||
|
# repo -- `mkrep .` on an existing checkout, or a second mkrep against the
|
||||||
|
# same target -- where a bare `git remote add origin` fails with "remote
|
||||||
|
# origin already exists" and takes the whole call down with it.
|
||||||
|
#
|
||||||
|
# No origin yet: adds it. An origin already pointing at <url>: reports that
|
||||||
|
# and succeeds, since the requested end state already holds. An origin
|
||||||
|
# pointing somewhere else: refuses, naming both URLs. Repointing is not
|
||||||
|
# silently assumed -- an origin the caller did not ask about is more likely
|
||||||
|
# a checkout mkrep was aimed at by mistake than one it should rewrite, so
|
||||||
|
# the fix belongs in the caller's hands (git remote set-url origin <url>).
|
||||||
|
#
|
||||||
|
# ARGUMENTS
|
||||||
|
# silent 1 to suppress the success/already-linked notes (mkrep's -s)
|
||||||
|
# url Remote URL origin should point at
|
||||||
|
#
|
||||||
|
# EXIT STATUS
|
||||||
|
# 0 origin now points at <url> (added, or already did)
|
||||||
|
# 1 git remote add failed, or origin points somewhere else
|
||||||
|
function _mkrep_add_origin --argument-names silent url
|
||||||
|
__fish_palette
|
||||||
|
|
||||||
|
set -l existing (git remote get-url origin 2>/dev/null)
|
||||||
|
|
||||||
|
if test -z "$existing"
|
||||||
|
git remote add origin $url
|
||||||
|
or begin
|
||||||
|
echo "$c_err""✘$c_reset Failed to add remote $c_arg$url$c_reset" >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
_mkrep_say $silent "$c_ok""✔$c_reset Linked remote $c_arg$url$c_reset"
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
if test "$existing" = "$url"
|
||||||
|
_mkrep_say $silent "$c_warn""→$c_reset origin already points at $c_arg$url$c_reset"
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
echo "$c_err""✘$c_reset origin already points at $c_arg$existing$c_reset, not $c_arg$url$c_reset — run $c_cmd""git remote set-url origin $url$c_reset to repoint it" >&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
+10
-8
@@ -6,7 +6,8 @@
|
|||||||
#
|
#
|
||||||
# DEPENDENCIES
|
# DEPENDENCIES
|
||||||
# _fish_mkdir_p, __fish_palette, _mkrep_say, _mkrep_verbose,
|
# _fish_mkdir_p, __fish_palette, _mkrep_say, _mkrep_verbose,
|
||||||
# _mkrep_default_remote_cmd, _mkrep_remote_url, _mkrep_repo_exists, git
|
# _mkrep_add_origin, _mkrep_default_remote_cmd, _mkrep_remote_url,
|
||||||
|
# _mkrep_repo_exists, git
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
# mkrep [--cd | --no-cd] [--mkdir | --no-mkdir] [--git | --no-git]
|
# mkrep [--cd | --no-cd] [--mkdir | --no-mkdir] [--git | --no-git]
|
||||||
@@ -28,7 +29,12 @@
|
|||||||
# empty slot because clean just emptied it.
|
# empty slot because clean just emptied it.
|
||||||
#
|
#
|
||||||
# --remote links an already-existing remote (git remote add origin
|
# --remote links an already-existing remote (git remote add origin
|
||||||
# <url>) -- it does not create anything. --new-remote creates one first
|
# <url>) -- it does not create anything. Linking is idempotent: an origin
|
||||||
|
# already pointing at that URL is reported and accepted, so rerunning
|
||||||
|
# mkrep against the same target, or pointing it at a checkout that is
|
||||||
|
# already linked, succeeds instead of failing on "remote origin already
|
||||||
|
# exists". An origin pointing somewhere else is an error, not a silent
|
||||||
|
# repoint. --new-remote creates one first
|
||||||
# by running a shell command template in the new repo directory, then
|
# by running a shell command template in the new repo directory, then
|
||||||
# nothing further is needed since the template itself does the linking
|
# nothing further is needed since the template itself does the linking
|
||||||
# (e.g. gh repo create {name} --source=. --remote=origin --push).
|
# (e.g. gh repo create {name} --source=. --remote=origin --push).
|
||||||
@@ -333,13 +339,11 @@ function mkrep --description 'Create a directory, cd into it, and git init it'
|
|||||||
|
|
||||||
if set -q _flag_remote
|
if set -q _flag_remote
|
||||||
_mkrep_verbose $silent $verbose "$c_dim""Running: git remote add origin $_flag_remote$c_reset"
|
_mkrep_verbose $silent $verbose "$c_dim""Running: git remote add origin $_flag_remote$c_reset"
|
||||||
git remote add origin $_flag_remote
|
_mkrep_add_origin $silent $_flag_remote
|
||||||
or begin
|
or begin
|
||||||
echo "$c_err""✘$c_reset Failed to add remote $c_arg$_flag_remote$c_reset" >&2
|
|
||||||
cd $orig_pwd
|
cd $orig_pwd
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
_mkrep_say $silent "$c_ok""✔$c_reset Linked remote $c_arg$_flag_remote$c_reset"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if set -q _flag_new_remote
|
if set -q _flag_new_remote
|
||||||
@@ -384,13 +388,11 @@ function mkrep --description 'Create a directory, cd into it, and git init it'
|
|||||||
if _mkrep_repo_exists $srv_type $USER $name
|
if _mkrep_repo_exists $srv_type $USER $name
|
||||||
set -l url (_mkrep_remote_url $srv_type $USER $name $srv_url)
|
set -l url (_mkrep_remote_url $srv_type $USER $name $srv_url)
|
||||||
_mkrep_say $silent "$c_warn""→$c_reset $c_arg$USER/$name$c_reset already exists on $srv_type; linking instead of creating"
|
_mkrep_say $silent "$c_warn""→$c_reset $c_arg$USER/$name$c_reset already exists on $srv_type; linking instead of creating"
|
||||||
git remote add origin $url
|
_mkrep_add_origin $silent $url
|
||||||
or begin
|
or begin
|
||||||
echo "$c_err""✘$c_reset Failed to add remote $c_arg$url$c_reset" >&2
|
|
||||||
cd $orig_pwd
|
cd $orig_pwd
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
_mkrep_say $silent "$c_ok""✔$c_reset Linked remote $c_arg$url$c_reset"
|
|
||||||
else
|
else
|
||||||
# Creating a repository on a live forge is the only outward-facing
|
# Creating a repository on a live forge is the only outward-facing
|
||||||
# thing mkrep does, and an exported $GIT_SERVER alone is enough to
|
# thing mkrep does, and an exported $GIT_SERVER alone is enough to
|
||||||
|
|||||||
@@ -163,6 +163,30 @@ check "--remote links origin to the given url" https://example.invalid/me/repo.g
|
|||||||
cd $start
|
cd $start
|
||||||
rm -rf $base
|
rm -rf $base
|
||||||
|
|
||||||
|
# `mkrep .` against an existing checkout, and a plain rerun against the same
|
||||||
|
# target, both reach `git remote add origin` on a repo that already has one.
|
||||||
|
# A bare add fails there with "remote origin already exists" and takes the
|
||||||
|
# whole call down, so linking has to accept the end state it already wanted.
|
||||||
|
section "mkrep: --remote is idempotent"
|
||||||
|
|
||||||
|
set -l base (_mkrep_sandbox)
|
||||||
|
set -l target $base/repo
|
||||||
|
mkrep --remote https://example.invalid/me/repo.git $target >/dev/null
|
||||||
|
mkrep --remote https://example.invalid/me/repo.git $target >/dev/null
|
||||||
|
check "relinking the same url exits 0" 0 $status
|
||||||
|
check "relinking leaves one origin" 1 (count (git -C $target remote))
|
||||||
|
set -l url (git -C $target remote get-url origin)
|
||||||
|
check "relinking leaves origin untouched" https://example.invalid/me/repo.git $url
|
||||||
|
|
||||||
|
# A different url is a different repo. Repointing a checkout the caller did
|
||||||
|
# not ask about is more likely a mistargeted mkrep than an intended rewrite.
|
||||||
|
mkrep --remote https://example.invalid/me/other.git $target >/dev/null 2>/tmp/mkrep-test-err
|
||||||
|
check "relinking a different url exits 1" 1 $status
|
||||||
|
set -l url (git -C $target remote get-url origin)
|
||||||
|
check "a refused relink leaves origin alone" https://example.invalid/me/repo.git $url
|
||||||
|
cd $start
|
||||||
|
rm -rf $base
|
||||||
|
|
||||||
section "mkrep: --remote and --new-remote are exclusive"
|
section "mkrep: --remote and --new-remote are exclusive"
|
||||||
|
|
||||||
set -l base (_mkrep_sandbox)
|
set -l base (_mkrep_sandbox)
|
||||||
|
|||||||
Reference in New Issue
Block a user