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
|
||||
# _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
|
||||
# mkrep [--cd | --no-cd] [--mkdir | --no-mkdir] [--git | --no-git]
|
||||
@@ -28,7 +29,12 @@
|
||||
# empty slot because clean just emptied it.
|
||||
#
|
||||
# --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
|
||||
# nothing further is needed since the template itself does the linking
|
||||
# (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
|
||||
_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
|
||||
echo "$c_err""✘$c_reset Failed to add remote $c_arg$_flag_remote$c_reset" >&2
|
||||
cd $orig_pwd
|
||||
return 1
|
||||
end
|
||||
_mkrep_say $silent "$c_ok""✔$c_reset Linked remote $c_arg$_flag_remote$c_reset"
|
||||
end
|
||||
|
||||
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
|
||||
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"
|
||||
git remote add origin $url
|
||||
_mkrep_add_origin $silent $url
|
||||
or begin
|
||||
echo "$c_err""✘$c_reset Failed to add remote $c_arg$url$c_reset" >&2
|
||||
cd $orig_pwd
|
||||
return 1
|
||||
end
|
||||
_mkrep_say $silent "$c_ok""✔$c_reset Linked remote $c_arg$url$c_reset"
|
||||
else
|
||||
# Creating a repository on a live forge is the only outward-facing
|
||||
# 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
|
||||
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"
|
||||
|
||||
set -l base (_mkrep_sandbox)
|
||||
|
||||
Reference in New Issue
Block a user