pyinfra 0.11.dev3__py3-none-any.whl → 3.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyinfra/__init__.py +9 -12
- pyinfra/__main__.py +4 -0
- pyinfra/api/__init__.py +18 -3
- pyinfra/api/arguments.py +406 -0
- pyinfra/api/arguments_typed.py +79 -0
- pyinfra/api/command.py +274 -0
- pyinfra/api/config.py +222 -28
- pyinfra/api/connect.py +33 -13
- pyinfra/api/connectors.py +27 -0
- pyinfra/api/deploy.py +65 -66
- pyinfra/api/exceptions.py +67 -18
- pyinfra/api/facts.py +253 -202
- pyinfra/api/host.py +413 -50
- pyinfra/api/inventory.py +121 -160
- pyinfra/api/operation.py +432 -262
- pyinfra/api/operations.py +273 -260
- pyinfra/api/state.py +302 -248
- pyinfra/api/util.py +291 -368
- pyinfra/connectors/base.py +173 -0
- pyinfra/connectors/chroot.py +212 -0
- pyinfra/connectors/docker.py +381 -0
- pyinfra/connectors/dockerssh.py +297 -0
- pyinfra/connectors/local.py +238 -0
- pyinfra/connectors/scp/__init__.py +1 -0
- pyinfra/connectors/scp/client.py +204 -0
- pyinfra/connectors/ssh.py +670 -0
- pyinfra/connectors/ssh_util.py +114 -0
- pyinfra/connectors/sshuserclient/client.py +309 -0
- pyinfra/connectors/sshuserclient/config.py +102 -0
- pyinfra/connectors/terraform.py +135 -0
- pyinfra/connectors/util.py +410 -0
- pyinfra/connectors/vagrant.py +183 -0
- pyinfra/context.py +145 -0
- pyinfra/facts/__init__.py +7 -6
- pyinfra/facts/apk.py +22 -7
- pyinfra/facts/apt.py +117 -60
- pyinfra/facts/brew.py +100 -15
- pyinfra/facts/bsdinit.py +23 -0
- pyinfra/facts/cargo.py +37 -0
- pyinfra/facts/choco.py +47 -0
- pyinfra/facts/crontab.py +195 -0
- pyinfra/facts/deb.py +94 -0
- pyinfra/facts/dnf.py +48 -0
- pyinfra/facts/docker.py +96 -23
- pyinfra/facts/efibootmgr.py +113 -0
- pyinfra/facts/files.py +630 -58
- pyinfra/facts/flatpak.py +77 -0
- pyinfra/facts/freebsd.py +70 -0
- pyinfra/facts/gem.py +19 -6
- pyinfra/facts/git.py +59 -14
- pyinfra/facts/gpg.py +150 -0
- pyinfra/facts/hardware.py +313 -167
- pyinfra/facts/iptables.py +72 -62
- pyinfra/facts/launchd.py +44 -0
- pyinfra/facts/lxd.py +17 -4
- pyinfra/facts/mysql.py +122 -86
- pyinfra/facts/npm.py +17 -9
- pyinfra/facts/openrc.py +71 -0
- pyinfra/facts/opkg.py +246 -0
- pyinfra/facts/pacman.py +50 -7
- pyinfra/facts/pip.py +24 -7
- pyinfra/facts/pipx.py +82 -0
- pyinfra/facts/pkg.py +15 -6
- pyinfra/facts/pkgin.py +35 -0
- pyinfra/facts/podman.py +54 -0
- pyinfra/facts/postgres.py +178 -0
- pyinfra/facts/postgresql.py +6 -147
- pyinfra/facts/rpm.py +105 -0
- pyinfra/facts/runit.py +77 -0
- pyinfra/facts/selinux.py +161 -0
- pyinfra/facts/server.py +746 -285
- pyinfra/facts/snap.py +88 -0
- pyinfra/facts/systemd.py +139 -0
- pyinfra/facts/sysvinit.py +59 -0
- pyinfra/facts/upstart.py +35 -0
- pyinfra/facts/util/__init__.py +17 -0
- pyinfra/facts/util/databases.py +4 -6
- pyinfra/facts/util/packaging.py +37 -6
- pyinfra/facts/util/units.py +30 -0
- pyinfra/facts/util/win_files.py +99 -0
- pyinfra/facts/vzctl.py +20 -13
- pyinfra/facts/xbps.py +35 -0
- pyinfra/facts/yum.py +34 -40
- pyinfra/facts/zfs.py +77 -0
- pyinfra/facts/zypper.py +42 -0
- pyinfra/local.py +45 -83
- pyinfra/operations/__init__.py +12 -0
- pyinfra/operations/apk.py +98 -0
- pyinfra/operations/apt.py +488 -0
- pyinfra/operations/brew.py +231 -0
- pyinfra/operations/bsdinit.py +59 -0
- pyinfra/operations/cargo.py +45 -0
- pyinfra/operations/choco.py +61 -0
- pyinfra/operations/crontab.py +191 -0
- pyinfra/operations/dnf.py +210 -0
- pyinfra/operations/docker.py +446 -0
- pyinfra/operations/files.py +1939 -0
- pyinfra/operations/flatpak.py +94 -0
- pyinfra/operations/freebsd/__init__.py +12 -0
- pyinfra/operations/freebsd/freebsd_update.py +70 -0
- pyinfra/operations/freebsd/pkg.py +219 -0
- pyinfra/operations/freebsd/service.py +116 -0
- pyinfra/operations/freebsd/sysrc.py +92 -0
- pyinfra/operations/gem.py +47 -0
- pyinfra/operations/git.py +419 -0
- pyinfra/operations/iptables.py +311 -0
- pyinfra/operations/launchd.py +45 -0
- pyinfra/operations/lxd.py +68 -0
- pyinfra/operations/mysql.py +609 -0
- pyinfra/operations/npm.py +57 -0
- pyinfra/operations/openrc.py +63 -0
- pyinfra/operations/opkg.py +88 -0
- pyinfra/operations/pacman.py +81 -0
- pyinfra/operations/pip.py +205 -0
- pyinfra/operations/pipx.py +102 -0
- pyinfra/operations/pkg.py +70 -0
- pyinfra/operations/pkgin.py +91 -0
- pyinfra/operations/postgres.py +436 -0
- pyinfra/operations/postgresql.py +30 -0
- pyinfra/operations/puppet.py +40 -0
- pyinfra/operations/python.py +72 -0
- pyinfra/operations/runit.py +184 -0
- pyinfra/operations/selinux.py +189 -0
- pyinfra/operations/server.py +1099 -0
- pyinfra/operations/snap.py +117 -0
- pyinfra/operations/ssh.py +216 -0
- pyinfra/operations/systemd.py +149 -0
- pyinfra/operations/sysvinit.py +141 -0
- pyinfra/operations/upstart.py +68 -0
- pyinfra/operations/util/__init__.py +12 -0
- pyinfra/operations/util/docker.py +251 -0
- pyinfra/operations/util/files.py +247 -0
- pyinfra/operations/util/packaging.py +336 -0
- pyinfra/operations/util/service.py +46 -0
- pyinfra/operations/vzctl.py +137 -0
- pyinfra/operations/xbps.py +77 -0
- pyinfra/operations/yum.py +210 -0
- pyinfra/operations/zfs.py +175 -0
- pyinfra/operations/zypper.py +192 -0
- pyinfra/progress.py +44 -32
- pyinfra/py.typed +0 -0
- pyinfra/version.py +9 -1
- pyinfra-3.5.1.dist-info/METADATA +141 -0
- pyinfra-3.5.1.dist-info/RECORD +159 -0
- {pyinfra-0.11.dev3.dist-info → pyinfra-3.5.1.dist-info}/WHEEL +1 -2
- pyinfra-3.5.1.dist-info/entry_points.txt +12 -0
- {pyinfra-0.11.dev3.dist-info → pyinfra-3.5.1.dist-info/licenses}/LICENSE.md +1 -1
- pyinfra_cli/__init__.py +1 -0
- pyinfra_cli/cli.py +780 -0
- pyinfra_cli/commands.py +66 -0
- pyinfra_cli/exceptions.py +155 -65
- pyinfra_cli/inventory.py +233 -89
- pyinfra_cli/log.py +39 -43
- pyinfra_cli/main.py +26 -495
- pyinfra_cli/prints.py +215 -156
- pyinfra_cli/util.py +172 -105
- pyinfra_cli/virtualenv.py +25 -20
- pyinfra/api/connectors/__init__.py +0 -21
- pyinfra/api/connectors/ansible.py +0 -99
- pyinfra/api/connectors/docker.py +0 -178
- pyinfra/api/connectors/local.py +0 -169
- pyinfra/api/connectors/ssh.py +0 -402
- pyinfra/api/connectors/sshuserclient/client.py +0 -105
- pyinfra/api/connectors/sshuserclient/config.py +0 -90
- pyinfra/api/connectors/util.py +0 -63
- pyinfra/api/connectors/vagrant.py +0 -155
- pyinfra/facts/init.py +0 -176
- pyinfra/facts/util/files.py +0 -102
- pyinfra/hook.py +0 -41
- pyinfra/modules/__init__.py +0 -11
- pyinfra/modules/apk.py +0 -64
- pyinfra/modules/apt.py +0 -272
- pyinfra/modules/brew.py +0 -122
- pyinfra/modules/files.py +0 -711
- pyinfra/modules/gem.py +0 -30
- pyinfra/modules/git.py +0 -115
- pyinfra/modules/init.py +0 -344
- pyinfra/modules/iptables.py +0 -271
- pyinfra/modules/lxd.py +0 -45
- pyinfra/modules/mysql.py +0 -347
- pyinfra/modules/npm.py +0 -47
- pyinfra/modules/pacman.py +0 -60
- pyinfra/modules/pip.py +0 -99
- pyinfra/modules/pkg.py +0 -43
- pyinfra/modules/postgresql.py +0 -245
- pyinfra/modules/puppet.py +0 -20
- pyinfra/modules/python.py +0 -37
- pyinfra/modules/server.py +0 -524
- pyinfra/modules/ssh.py +0 -150
- pyinfra/modules/util/files.py +0 -52
- pyinfra/modules/util/packaging.py +0 -118
- pyinfra/modules/vzctl.py +0 -133
- pyinfra/modules/yum.py +0 -171
- pyinfra/pseudo_modules.py +0 -64
- pyinfra-0.11.dev3.dist-info/.DS_Store +0 -0
- pyinfra-0.11.dev3.dist-info/METADATA +0 -135
- pyinfra-0.11.dev3.dist-info/RECORD +0 -95
- pyinfra-0.11.dev3.dist-info/entry_points.txt +0 -3
- pyinfra-0.11.dev3.dist-info/top_level.txt +0 -2
- pyinfra_cli/__main__.py +0 -40
- pyinfra_cli/config.py +0 -92
- /pyinfra/{modules/util → connectors}/__init__.py +0 -0
- /pyinfra/{api/connectors → connectors}/sshuserclient/__init__.py +0 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Manage git repositories and configuration.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import re
|
|
8
|
+
|
|
9
|
+
from pyinfra import host
|
|
10
|
+
from pyinfra.api import OperationError, operation
|
|
11
|
+
from pyinfra.facts.files import Directory, File
|
|
12
|
+
from pyinfra.facts.git import GitBranch, GitConfig, GitTag, GitTrackingBranch
|
|
13
|
+
|
|
14
|
+
from . import files, ssh
|
|
15
|
+
from .util.files import chown, unix_path_join
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@operation()
|
|
19
|
+
def config(key: str, value: str, multi_value=False, repo: str | None = None, system=False):
|
|
20
|
+
"""
|
|
21
|
+
Manage git config at repository, user or system level.
|
|
22
|
+
|
|
23
|
+
+ key: the key of the config to ensure
|
|
24
|
+
+ value: the value this key should have
|
|
25
|
+
+ multi_value: Add the value rather than set it for settings that can have multiple values
|
|
26
|
+
+ repo: specify the git repo path to edit local config (defaults to global)
|
|
27
|
+
+ system: whether, when ``repo`` is unspecified, to work at system level (or default to global)
|
|
28
|
+
|
|
29
|
+
**Examples:**
|
|
30
|
+
|
|
31
|
+
.. code:: python
|
|
32
|
+
|
|
33
|
+
git.config(
|
|
34
|
+
name="Always prune specified repo",
|
|
35
|
+
key="fetch.prune",
|
|
36
|
+
value="true",
|
|
37
|
+
repo="/usr/local/src/pyinfra",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
git.config(
|
|
41
|
+
name="Ensure user name is set for all repos of specified user",
|
|
42
|
+
key="user.name",
|
|
43
|
+
value="Anon E. Mouse",
|
|
44
|
+
_sudo=True,
|
|
45
|
+
_sudo_user="anon"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
git.config(
|
|
49
|
+
name="Ensure same date format for all users",
|
|
50
|
+
key="log.date",
|
|
51
|
+
value="iso",
|
|
52
|
+
system=True
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
existing_config = {}
|
|
58
|
+
|
|
59
|
+
if not repo:
|
|
60
|
+
existing_config = host.get_fact(GitConfig, system=system)
|
|
61
|
+
|
|
62
|
+
# Only get the config if the repo exists at this stage
|
|
63
|
+
elif host.get_fact(Directory, path=unix_path_join(repo, ".git")):
|
|
64
|
+
existing_config = host.get_fact(GitConfig, repo=repo)
|
|
65
|
+
|
|
66
|
+
if repo is None:
|
|
67
|
+
base_command = "git config" + (" --system" if system else " --global")
|
|
68
|
+
else:
|
|
69
|
+
base_command = "cd {0} && git config --local".format(repo)
|
|
70
|
+
|
|
71
|
+
if not multi_value and existing_config.get(key) != [value]:
|
|
72
|
+
yield '{0} {1} "{2}"'.format(base_command, key, value)
|
|
73
|
+
|
|
74
|
+
elif multi_value and value not in existing_config.get(key, []):
|
|
75
|
+
yield '{0} --add {1} "{2}"'.format(base_command, key, value)
|
|
76
|
+
|
|
77
|
+
else:
|
|
78
|
+
host.noop("git config {0} is set to {1}".format(key, value))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@operation()
|
|
82
|
+
def repo(
|
|
83
|
+
src: str,
|
|
84
|
+
dest: str,
|
|
85
|
+
branch: str | None = None,
|
|
86
|
+
pull=True,
|
|
87
|
+
rebase=False,
|
|
88
|
+
user: str | None = None,
|
|
89
|
+
group: str | None = None,
|
|
90
|
+
ssh_keyscan=False,
|
|
91
|
+
update_submodules=False,
|
|
92
|
+
recursive_submodules=False,
|
|
93
|
+
):
|
|
94
|
+
"""
|
|
95
|
+
Clone/pull git repositories.
|
|
96
|
+
|
|
97
|
+
+ src: the git source URL
|
|
98
|
+
+ dest: directory to clone to
|
|
99
|
+
+ branch: branch to pull/checkout
|
|
100
|
+
+ pull: pull any changes for the branch
|
|
101
|
+
+ rebase: when pulling, use ``--rebase``
|
|
102
|
+
+ user: chown files to this user after
|
|
103
|
+
+ group: chown files to this group after
|
|
104
|
+
+ ssh_keyscan: keyscan the remote host if not in known_hosts before clone/pull
|
|
105
|
+
+ update_submodules: update any git submodules
|
|
106
|
+
+ recursive_submodules: update git submodules recursively
|
|
107
|
+
|
|
108
|
+
**Example:**
|
|
109
|
+
|
|
110
|
+
.. code:: python
|
|
111
|
+
|
|
112
|
+
git.repo(
|
|
113
|
+
name="Clone repo",
|
|
114
|
+
src="https://github.com/Fizzadar/pyinfra.git",
|
|
115
|
+
dest="/usr/local/src/pyinfra",
|
|
116
|
+
)
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
# Ensure our target directory exists
|
|
120
|
+
yield from files.directory._inner(dest)
|
|
121
|
+
|
|
122
|
+
# Do we need to scan for the remote host key?
|
|
123
|
+
if ssh_keyscan:
|
|
124
|
+
# Attempt to parse the domain from the git repository
|
|
125
|
+
domain = re.match(r"^[a-zA-Z0-9]+@([0-9a-zA-Z\.\-]+)", src)
|
|
126
|
+
|
|
127
|
+
if domain:
|
|
128
|
+
yield from ssh.keyscan._inner(domain.group(1))
|
|
129
|
+
else:
|
|
130
|
+
raise OperationError(
|
|
131
|
+
"Could not parse domain (to SSH keyscan) from: {0}".format(src),
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Store git commands for directory prefix
|
|
135
|
+
git_commands = []
|
|
136
|
+
git_dir = unix_path_join(dest, ".git")
|
|
137
|
+
is_repo = host.get_fact(Directory, path=git_dir)
|
|
138
|
+
|
|
139
|
+
# Cloning new repo?
|
|
140
|
+
if not is_repo:
|
|
141
|
+
if branch:
|
|
142
|
+
git_commands.append("clone {0} --branch {1} .".format(src, branch))
|
|
143
|
+
else:
|
|
144
|
+
git_commands.append("clone {0} .".format(src))
|
|
145
|
+
# Ensuring existing repo
|
|
146
|
+
else:
|
|
147
|
+
is_tag = False
|
|
148
|
+
if branch and host.get_fact(GitBranch, repo=dest) != branch:
|
|
149
|
+
git_commands.append("fetch") # fetch to ensure we have the branch locally
|
|
150
|
+
git_commands.append("checkout {0}".format(branch))
|
|
151
|
+
if branch and branch in (host.get_fact(GitTag, repo=dest) or []):
|
|
152
|
+
git_commands.append("checkout {0}".format(branch))
|
|
153
|
+
is_tag = True
|
|
154
|
+
if pull and not is_tag:
|
|
155
|
+
if rebase:
|
|
156
|
+
git_commands.append("pull --rebase")
|
|
157
|
+
else:
|
|
158
|
+
git_commands.append("pull")
|
|
159
|
+
|
|
160
|
+
if update_submodules:
|
|
161
|
+
if recursive_submodules:
|
|
162
|
+
git_commands.append("submodule update --init --recursive")
|
|
163
|
+
else:
|
|
164
|
+
git_commands.append("submodule update --init")
|
|
165
|
+
|
|
166
|
+
# Attach prefixes for directory
|
|
167
|
+
command_prefix = "cd {0} && git".format(dest)
|
|
168
|
+
git_commands = ["{0} {1}".format(command_prefix, command) for command in git_commands]
|
|
169
|
+
|
|
170
|
+
for cmd in git_commands:
|
|
171
|
+
yield cmd
|
|
172
|
+
|
|
173
|
+
# Apply any user or group if we did anything
|
|
174
|
+
if git_commands and (user or group):
|
|
175
|
+
yield chown(dest, user, group, recursive=True)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
@operation()
|
|
179
|
+
def worktree(
|
|
180
|
+
worktree: str,
|
|
181
|
+
repo: str | None = None,
|
|
182
|
+
detached=False,
|
|
183
|
+
new_branch: str | None = None,
|
|
184
|
+
commitish: str | None = None,
|
|
185
|
+
pull=True,
|
|
186
|
+
rebase=False,
|
|
187
|
+
from_remote_branch: tuple[str, str] | None = None,
|
|
188
|
+
present=True,
|
|
189
|
+
assume_repo_exists=False,
|
|
190
|
+
force=False,
|
|
191
|
+
user: str | None = None,
|
|
192
|
+
group: str | None = None,
|
|
193
|
+
):
|
|
194
|
+
"""
|
|
195
|
+
Manage git worktrees.
|
|
196
|
+
|
|
197
|
+
+ worktree: git working tree directory
|
|
198
|
+
+ repo: git main repository directory
|
|
199
|
+
+ detached: create a working tree with a detached HEAD
|
|
200
|
+
+ new_branch: local branch name created at the same time than the worktree
|
|
201
|
+
+ commitish: from which git commit, branch, ... the worktree is created
|
|
202
|
+
+ pull: pull any changes from a remote branch if set
|
|
203
|
+
+ rebase: when pulling, use ``--rebase``
|
|
204
|
+
+ from_remote_branch: a 2-tuple ``(remote, branch)`` that identifies a remote branch
|
|
205
|
+
+ present: whether the working tree should exist
|
|
206
|
+
+ assume_repo_exists: whether to assume the main repo exists
|
|
207
|
+
+ force: whether to use ``--force`` when adding/removing worktrees
|
|
208
|
+
+ user: chown files to this user after
|
|
209
|
+
+ group: chown files to this group after
|
|
210
|
+
|
|
211
|
+
**Examples:**
|
|
212
|
+
|
|
213
|
+
.. code:: python
|
|
214
|
+
|
|
215
|
+
git.worktree(
|
|
216
|
+
name="Create a worktree from the current repo `HEAD`",
|
|
217
|
+
repo="/usr/local/src/pyinfra/master",
|
|
218
|
+
worktree="/usr/local/src/pyinfra/hotfix"
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
git.worktree(
|
|
222
|
+
name="Create a worktree from the commit `4e091aa0`",
|
|
223
|
+
repo="/usr/local/src/pyinfra/master",
|
|
224
|
+
worktree="/usr/local/src/pyinfra/hotfix",
|
|
225
|
+
commitish="4e091aa0"
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
git.worktree(
|
|
229
|
+
name="Create a worktree from the tag `4e091aa0`, even if already registered",
|
|
230
|
+
repo="/usr/local/src/pyinfra/master",
|
|
231
|
+
worktree="/usr/local/src/pyinfra/2.x",
|
|
232
|
+
commitish="2.x",
|
|
233
|
+
force=True
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
git.worktree(
|
|
237
|
+
name="Create a worktree with a new local branch `v1.0`",
|
|
238
|
+
repo="/usr/local/src/pyinfra/master",
|
|
239
|
+
worktree="/usr/local/src/pyinfra/hotfix",
|
|
240
|
+
new_branch="v1.0",
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
git.worktree(
|
|
244
|
+
name="Create a worktree from the commit 4e091aa0 with the new local branch `v1.0`",
|
|
245
|
+
repo="/usr/local/src/pyinfra/master",
|
|
246
|
+
worktree="/usr/local/src/pyinfra/hotfix",
|
|
247
|
+
new_branch="v1.0",
|
|
248
|
+
commitish="4e091aa0"
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
git.worktree(
|
|
252
|
+
name="Create a worktree with a detached `HEAD`",
|
|
253
|
+
repo="/usr/local/src/pyinfra/master",
|
|
254
|
+
worktree="/usr/local/src/pyinfra/hotfix",
|
|
255
|
+
detached=True,
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
git.worktree(
|
|
259
|
+
name="Create a worktree with a detached `HEAD` from commit `4e091aa0`",
|
|
260
|
+
repo="/usr/local/src/pyinfra/master",
|
|
261
|
+
worktree="/usr/local/src/pyinfra/hotfix",
|
|
262
|
+
commitish="4e091aa0",
|
|
263
|
+
detached=True,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
git.worktree(
|
|
267
|
+
name="Create a worktree from the existing local branch `v1.0`",
|
|
268
|
+
repo="/usr/local/src/pyinfra/master",
|
|
269
|
+
worktree="/usr/local/src/pyinfra/hotfix",
|
|
270
|
+
commitish="v1.0"
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
git.worktree(
|
|
274
|
+
name="Create a worktree with a new branch `v1.0` that tracks `origin/v1.0`",
|
|
275
|
+
repo="/usr/local/src/pyinfra/master",
|
|
276
|
+
worktree="/usr/local/src/pyinfra/hotfix",
|
|
277
|
+
new_branch="v1.0",
|
|
278
|
+
commitish="v1.0"
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
git.worktree(
|
|
282
|
+
name="Idempotent worktree creation, never pulls",
|
|
283
|
+
repo="/usr/local/src/pyinfra/master",
|
|
284
|
+
worktree="/usr/local/src/pyinfra/hotfix",
|
|
285
|
+
new_branch="v1.0",
|
|
286
|
+
commitish="v1.0",
|
|
287
|
+
pull=False
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
git.worktree(
|
|
291
|
+
name="Pull an existing worktree already linked to a tracking branch",
|
|
292
|
+
repo="/usr/local/src/pyinfra/master",
|
|
293
|
+
worktree="/usr/local/src/pyinfra/hotfix"
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
git.worktree(
|
|
297
|
+
name="Pull an existing worktree from a specific remote branch",
|
|
298
|
+
repo="/usr/local/src/pyinfra/master",
|
|
299
|
+
worktree="/usr/local/src/pyinfra/hotfix",
|
|
300
|
+
from_remote_branch=("origin", "master")
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
git.worktree(
|
|
304
|
+
name="Remove a worktree",
|
|
305
|
+
worktree="/usr/local/src/pyinfra/hotfix",
|
|
306
|
+
present=False,
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
git.worktree(
|
|
310
|
+
name="Remove an unclean worktree",
|
|
311
|
+
worktree="/usr/local/src/pyinfra/hotfix",
|
|
312
|
+
present=False,
|
|
313
|
+
force=True,
|
|
314
|
+
)
|
|
315
|
+
"""
|
|
316
|
+
|
|
317
|
+
# Doesn't exist & we want it
|
|
318
|
+
if not host.get_fact(Directory, path=worktree) and present:
|
|
319
|
+
# be sure that `repo` is a GIT repository
|
|
320
|
+
if not assume_repo_exists and not host.get_fact(
|
|
321
|
+
Directory,
|
|
322
|
+
path=unix_path_join(repo, ".git"),
|
|
323
|
+
):
|
|
324
|
+
raise OperationError(
|
|
325
|
+
"The following folder is not a valid GIT repository : {0}".format(repo),
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
command_parts = ["cd {0} && git worktree add".format(repo)]
|
|
329
|
+
|
|
330
|
+
if new_branch:
|
|
331
|
+
command_parts.append("-b {0}".format(new_branch))
|
|
332
|
+
elif detached:
|
|
333
|
+
command_parts.append("--detach")
|
|
334
|
+
|
|
335
|
+
if force:
|
|
336
|
+
command_parts.append("--force")
|
|
337
|
+
|
|
338
|
+
command_parts.append(worktree)
|
|
339
|
+
|
|
340
|
+
if commitish:
|
|
341
|
+
command_parts.append(commitish)
|
|
342
|
+
|
|
343
|
+
yield " ".join(command_parts)
|
|
344
|
+
|
|
345
|
+
# Apply any user or group
|
|
346
|
+
if user or group:
|
|
347
|
+
yield chown(worktree, user, group, recursive=True)
|
|
348
|
+
|
|
349
|
+
# It exists and we don't want it
|
|
350
|
+
elif host.get_fact(Directory, path=worktree) and not present:
|
|
351
|
+
command = "cd {0} && git worktree remove .".format(worktree)
|
|
352
|
+
|
|
353
|
+
if force:
|
|
354
|
+
command += " --force"
|
|
355
|
+
|
|
356
|
+
yield command
|
|
357
|
+
|
|
358
|
+
# It exists and we still want it => pull/rebase it
|
|
359
|
+
elif host.get_fact(Directory, path=worktree) and present:
|
|
360
|
+
if not pull:
|
|
361
|
+
host.noop("Pull is disabled")
|
|
362
|
+
|
|
363
|
+
# pull the worktree only if it's already linked to a tracking branch or
|
|
364
|
+
# if a remote branch is set
|
|
365
|
+
elif host.get_fact(GitTrackingBranch, repo=worktree) or from_remote_branch:
|
|
366
|
+
command = "cd {0} && git pull".format(worktree)
|
|
367
|
+
|
|
368
|
+
if rebase:
|
|
369
|
+
command += " --rebase"
|
|
370
|
+
|
|
371
|
+
if from_remote_branch:
|
|
372
|
+
if len(from_remote_branch) != 2 or type(from_remote_branch) not in (tuple, list):
|
|
373
|
+
raise OperationError(
|
|
374
|
+
"The remote branch must be a 2-tuple (remote, branch) such as "
|
|
375
|
+
'("origin", "master")',
|
|
376
|
+
)
|
|
377
|
+
command += " {0} {1}".format(*from_remote_branch)
|
|
378
|
+
|
|
379
|
+
yield command
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
@operation()
|
|
383
|
+
def bare_repo(
|
|
384
|
+
path: str,
|
|
385
|
+
user: str | None = None,
|
|
386
|
+
group: str | None = None,
|
|
387
|
+
present=True,
|
|
388
|
+
):
|
|
389
|
+
"""
|
|
390
|
+
Create bare git repositories.
|
|
391
|
+
|
|
392
|
+
+ path: path to the folder
|
|
393
|
+
+ present: whether the bare repository should exist
|
|
394
|
+
+ user: chown files to this user after
|
|
395
|
+
+ group: chown files to this group after
|
|
396
|
+
|
|
397
|
+
**Example:**
|
|
398
|
+
|
|
399
|
+
.. code:: python
|
|
400
|
+
|
|
401
|
+
git.bare_repo(
|
|
402
|
+
name="Create bare repo",
|
|
403
|
+
path="/home/git/test.git",
|
|
404
|
+
)
|
|
405
|
+
"""
|
|
406
|
+
|
|
407
|
+
yield from files.directory._inner(path, present=present)
|
|
408
|
+
|
|
409
|
+
if present:
|
|
410
|
+
head_filename = unix_path_join(path, "HEAD")
|
|
411
|
+
head_file = host.get_fact(File, path=head_filename)
|
|
412
|
+
|
|
413
|
+
if not head_file:
|
|
414
|
+
yield "git init --bare {0}".format(path)
|
|
415
|
+
if user or group:
|
|
416
|
+
yield chown(path, user, group, recursive=True)
|
|
417
|
+
else:
|
|
418
|
+
if (user and head_file["user"] != user) or (group and head_file["group"] != group):
|
|
419
|
+
yield chown(path, user, group, recursive=True)
|