PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/git.py |
""" Support for the Git SCM """ import copy import glob import logging import os import re import stat import salt.utils.args import salt.utils.data import salt.utils.files import salt.utils.functools import salt.utils.itertools import salt.utils.path import salt.utils.platform import salt.utils.stringutils import salt.utils.templates import salt.utils.url from salt.exceptions import CommandExecutionError, SaltInvocationError from salt.utils.versions import LooseVersion log = logging.getLogger(__name__) __func_alias__ = {"rm_": "rm"} def __virtual__(): """ Only load if git exists on the system """ if salt.utils.path.which("git") is None: return (False, "The git execution module cannot be loaded: git unavailable.") else: return True def _check_worktree_support(failhard=True): """ Ensure that we don't try to operate on worktrees in git < 2.5.0. """ git_version = version(versioninfo=False) if LooseVersion(git_version) < LooseVersion("2.5.0"): if failhard: raise CommandExecutionError( "Worktrees are only supported in git 2.5.0 and newer " "(detected git version: {})".format(git_version) ) return False return True def _config_getter( get_opt, key, value_regex=None, cwd=None, user=None, password=None, ignore_retcode=False, output_encoding=None, **kwargs, ): """ Common code for config.get_* functions, builds and runs the git CLI command and returns the result dict for the calling function to parse. """ kwargs = salt.utils.args.clean_kwargs(**kwargs) global_ = kwargs.pop("global", False) if kwargs: salt.utils.args.invalid_kwargs(kwargs) if cwd is None: if not global_: raise SaltInvocationError("'cwd' argument required unless global=True") else: cwd = _expand_path(cwd, user) if get_opt == "--get-regexp": if value_regex is not None and not isinstance(value_regex, str): value_regex = str(value_regex) else: # Ignore value_regex value_regex = None command = ["git", "config"] command.extend( _which_git_config(global_, cwd, user, password, output_encoding=output_encoding) ) command.append(get_opt) command.append(key) if value_regex is not None: command.append(value_regex) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, failhard=False, output_encoding=output_encoding, ) def _expand_path(cwd, user): """ Expand home directory """ try: to_expand = "~" + user if user else "~" except TypeError: # Users should never be numeric but if we don't account for this then # we're going to get a traceback if someone passes this invalid input. to_expand = "~" + str(user) if user else "~" try: return os.path.join(os.path.expanduser(to_expand), cwd) except AttributeError: return os.path.join(os.path.expanduser(to_expand), str(cwd)) def _path_is_executable_others(path): """ Check every part of path for executable permission """ prevpath = None while path and path != prevpath: try: if not os.stat(path).st_mode & stat.S_IXOTH: return False except OSError: return False prevpath = path path, _ = os.path.split(path) return True def _format_opts(opts): """ Common code to inspect opts and split them if necessary """ if opts is None: return [] elif isinstance(opts, list): new_opts = [] for item in opts: if isinstance(item, str): new_opts.append(item) else: new_opts.append(str(item)) return new_opts else: if not isinstance(opts, str): opts = [str(opts)] else: opts = salt.utils.args.shlex_split(opts) opts = salt.utils.data.decode(opts) try: if opts[-1] == "--": # Strip the '--' if it was passed at the end of the opts string, # it'll be added back (if necessary) in the calling function. # Putting this check here keeps it from having to be repeated every # time _format_opts() is invoked. return opts[:-1] except IndexError: pass return opts def _format_git_opts(opts): """ Do a version check and make sure that the installed version of git can support git -c """ if opts: version_ = version(versioninfo=False) if LooseVersion(version_) < LooseVersion("1.7.2"): raise SaltInvocationError( "git_opts is only supported for git versions >= 1.7.2 " "(detected: {})".format(version_) ) return _format_opts(opts) def _find_ssh_exe(): """ Windows only: search for Git's bundled ssh.exe in known locations """ # Known locations for Git's ssh.exe in Windows globmasks = [ os.path.join( os.getenv("SystemDrive"), os.sep, "Program Files*", "Git", "usr", "bin", "ssh.exe", ), os.path.join( os.getenv("SystemDrive"), os.sep, "Program Files*", "Git", "bin", "ssh.exe" ), ] for globmask in globmasks: ssh_exe = glob.glob(globmask) if ssh_exe and os.path.isfile(ssh_exe[0]): ret = ssh_exe[0] break else: ret = None return ret def _git_run( command, cwd=None, user=None, password=None, identity=None, ignore_retcode=False, failhard=True, redirect_stderr=False, saltenv="base", output_encoding=None, **kwargs, ): """ simple, throw an exception with the error message on an error return code. this function may be moved to the command module, spliced with 'cmd.run_all', and used as an alternative to 'cmd.run_all'. Some commands don't return proper retcodes, so this can't replace 'cmd.run_all'. """ env = {} if identity: _salt_cli = __opts__.get("__cli", "") errors = [] missing_keys = [] # if the statefile provides multiple identities, they need to be tried # (but also allow a string instead of a list) if not isinstance(identity, list): # force it into a list identity = [identity] # try each of the identities, independently tmp_identity_file = None for id_file in identity: if "salt://" in id_file: with salt.utils.files.set_umask(0o077): tmp_identity_file = salt.utils.files.mkstemp() _id_file = id_file id_file = __salt__["cp.get_file"]( id_file, tmp_identity_file, saltenv ) if not id_file: log.error("identity %s does not exist.", _id_file) __salt__["file.remove"](tmp_identity_file) continue else: if user: os.chown(id_file, __salt__["file.user_to_uid"](user), -1) else: if not __salt__["file.file_exists"](id_file): missing_keys.append(id_file) log.error("identity %s does not exist.", id_file) continue env = {"GIT_IDENTITY": id_file} # copy wrapper to area accessible by ``runas`` user # currently no support in windows for wrapping git ssh ssh_id_wrapper = os.path.abspath( os.path.join( salt.utils.templates.TEMPLATE_DIRNAME, "git/ssh-id-wrapper" ) ) tmp_ssh_wrapper = None if salt.utils.platform.is_windows(): ssh_exe = _find_ssh_exe() if ssh_exe is None: raise CommandExecutionError( "Failed to find ssh.exe, unable to use identity file" ) env["GIT_SSH_EXE"] = ssh_exe # Use the windows batch file instead of the bourne shell script ssh_id_wrapper += ".bat" env["GIT_SSH"] = ssh_id_wrapper elif not user or _path_is_executable_others(ssh_id_wrapper): env["GIT_SSH"] = ssh_id_wrapper else: tmp_ssh_wrapper = salt.utils.files.mkstemp() salt.utils.files.copyfile(ssh_id_wrapper, tmp_ssh_wrapper) os.chmod(tmp_ssh_wrapper, 0o500) os.chown(tmp_ssh_wrapper, __salt__["file.user_to_uid"](user), -1) env["GIT_SSH"] = tmp_ssh_wrapper if "salt-call" not in _salt_cli and __utils__["ssh.key_is_encrypted"]( id_file ): errors.append( "Identity file {} is passphrase-protected and cannot be " "used in a non-interactive command. Using salt-call from " "the minion will allow a passphrase-protected key to be " "used.".format(id_file) ) continue log.info("Attempting git authentication using identity file %s", id_file) try: result = __salt__["cmd.run_all"]( command, cwd=cwd, runas=user, password=password, env=env, python_shell=False, log_callback=salt.utils.url.redact_http_basic_auth, ignore_retcode=ignore_retcode, redirect_stderr=redirect_stderr, output_encoding=output_encoding, **kwargs, ) finally: if tmp_ssh_wrapper: # Cleanup the temporary ssh wrapper file try: __salt__["file.remove"](tmp_ssh_wrapper) log.debug("Removed ssh wrapper file %s", tmp_ssh_wrapper) except AttributeError: # No wrapper was used pass except (SaltInvocationError, CommandExecutionError) as exc: log.warning( "Failed to remove ssh wrapper file %s: %s", tmp_ssh_wrapper, exc, ) if tmp_identity_file: # Cleanup the temporary identity file try: __salt__["file.remove"](tmp_identity_file) log.debug("Removed identity file %s", tmp_identity_file) except AttributeError: # No identify file was used pass except (SaltInvocationError, CommandExecutionError) as exc: log.warning( "Failed to remove identity file %s: %s", tmp_identity_file, exc, ) # If the command was successful, no need to try additional IDs if result["retcode"] == 0: return result else: err = result["stdout" if redirect_stderr else "stderr"] if err: errors.append(salt.utils.url.redact_http_basic_auth(err)) # We've tried all IDs and still haven't passed, so error out if failhard: msg = "Unable to authenticate using identity file:\n\n{}".format( "\n".join(errors) ) if missing_keys: if errors: msg += "\n\n" msg += "The following identity file(s) were not found: {}".format( ", ".join(missing_keys) ) raise CommandExecutionError(msg) return result else: result = __salt__["cmd.run_all"]( command, cwd=cwd, runas=user, password=password, env=env, python_shell=False, log_callback=salt.utils.url.redact_http_basic_auth, ignore_retcode=ignore_retcode, redirect_stderr=redirect_stderr, output_encoding=output_encoding, **kwargs, ) if result["retcode"] == 0: return result else: if failhard: gitcommand = " ".join(command) if isinstance(command, list) else command msg = "Command '{}' failed".format( salt.utils.url.redact_http_basic_auth(gitcommand) ) err = result["stdout" if redirect_stderr else "stderr"] if err: msg += f": {salt.utils.url.redact_http_basic_auth(err)}" raise CommandExecutionError(msg) return result def _get_toplevel(path, user=None, password=None, output_encoding=None): """ Use git rev-parse to return the top level of a repo """ return _git_run( ["git", "rev-parse", "--show-toplevel"], cwd=path, user=user, password=password, output_encoding=output_encoding, )["stdout"] def _git_config(cwd, user, password, output_encoding=None): """ Helper to retrieve git config options """ contextkey = "git.config." + cwd if contextkey not in __context__: git_dir = rev_parse( cwd, opts=["--git-dir"], user=user, password=password, ignore_retcode=True, output_encoding=output_encoding, ) if not os.path.isabs(git_dir): paths = (cwd, git_dir, "config") else: paths = (git_dir, "config") __context__[contextkey] = os.path.join(*paths) return __context__[contextkey] def _which_git_config(global_, cwd, user, password, output_encoding=None): """ Based on whether global or local config is desired, return a list of CLI args to include in the git config command. """ if global_: return ["--global"] version_ = LooseVersion(version(versioninfo=False)) if version_ >= LooseVersion("1.7.10.2"): # --local added in 1.7.10.2 return ["--local"] else: # For earlier versions, need to specify the path to the git config file return [ "--file", _git_config(cwd, user, password, output_encoding=output_encoding), ] def add( cwd, filename, opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ .. versionchanged:: 2015.8.0 The ``--verbose`` command line argument is now implied Interface to `git-add(1)`_ cwd The path to the git checkout filename The location of the file/directory to add, relative to ``cwd`` opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``add`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-add(1)`: http://git-scm.com/docs/git-add CLI Examples: .. code-block:: bash salt myminion git.add /path/to/repo foo/bar.py salt myminion git.add /path/to/repo foo/bar.py opts='--dry-run' """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.extend(["add", "--verbose"]) command.extend([x for x in _format_opts(opts) if x not in ("-v", "--verbose")]) command.extend(["--", filename]) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def archive( cwd, output, rev="HEAD", prefix=None, git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, **kwargs, ): """ .. versionchanged:: 2015.8.0 Returns ``True`` if successful, raises an error if not. Interface to `git-archive(1)`_, exports a tarball/zip file of the repository cwd The path to be archived .. note:: ``git archive`` permits a partial archive to be created. Thus, this path does not need to be the root of the git repository. Only the files within the directory specified by ``cwd`` (and its subdirectories) will be in the resulting archive. For example, if there is a git checkout at ``/tmp/foo``, then passing ``/tmp/foo/bar`` as the ``cwd`` will result in just the files underneath ``/tmp/foo/bar`` to be exported as an archive. output The path of the archive to be created overwrite : False Unless set to ``True``, Salt will over overwrite an existing archive at the path specified by the ``output`` argument. .. versionadded:: 2015.8.0 rev : HEAD The revision from which to create the archive format Manually specify the file format of the resulting archive. This argument can be omitted, and ``git archive`` will attempt to guess the archive type (and compression) from the filename. ``zip``, ``tar``, ``tar.gz``, and ``tgz`` are extensions that are recognized automatically, and git can be configured to support other archive types with the addition of git configuration keys. See the `git-archive(1)`_ manpage explanation of the ``--format`` argument (as well as the ``CONFIGURATION`` section of the manpage) for further information. .. versionadded:: 2015.8.0 prefix Prepend ``<prefix>`` to every filename in the archive. If unspecified, the name of the directory at the top level of the repository will be used as the prefix (e.g. if ``cwd`` is set to ``/foo/bar/baz``, the prefix will be ``baz``, and the resulting archive will contain a top-level directory by that name). .. note:: The default behavior if the ``--prefix`` option for ``git archive`` is not specified is to not prepend a prefix, so Salt's behavior differs slightly from ``git archive`` in this respect. Use ``prefix=''`` to create an archive with no prefix. .. versionchanged:: 2015.8.0 The behavior of this argument has been changed slightly. As of this version, it is necessary to include the trailing slash when specifying a prefix, if the prefix is intended to create a top-level directory. git_opts Any additional options to add to git command itself (not the ``archive`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-archive(1)`: http://git-scm.com/docs/git-archive CLI Example: .. code-block:: bash salt myminion git.archive /path/to/repo /path/to/archive.tar """ cwd = _expand_path(cwd, user) output = _expand_path(output, user) # Sanitize kwargs and make sure that no invalid ones were passed. This # allows us to accept 'format' as an argument to this function without # shadowing the format() global, while also not allowing unwanted arguments # to be passed. kwargs = salt.utils.args.clean_kwargs(**kwargs) format_ = kwargs.pop("format", None) if kwargs: salt.utils.args.invalid_kwargs(kwargs) command = ["git"] + _format_git_opts(git_opts) command.append("archive") # If prefix was set to '' then we skip adding the --prefix option, but if # it was not passed (i.e. None) we use the cwd. if prefix != "": if not prefix: prefix = os.path.basename(cwd) + os.sep command.extend(["--prefix", prefix]) if format_: command.extend(["--format", format_]) command.extend(["--output", output, rev]) _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) # No output (unless --verbose is used, and we don't want all files listed # in the output in case there are thousands), so just return True. If there # was an error in the git command, it will have already raised an exception # and we will never get to this return statement. return True def branch( cwd, name=None, opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ Interface to `git-branch(1)`_ cwd The path to the git checkout name Name of the branch on which to operate. If not specified, the current branch will be assumed. opts Any additional options to add to the command line, in a single string .. note:: To create a branch based on something other than HEAD, pass the name of the revision as ``opts``. If the revision is in the format ``remotename/branch``, then this will also set the remote tracking branch. Additionally, on the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``branch`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-branch(1)`: http://git-scm.com/docs/git-branch CLI Examples: .. code-block:: bash # Set remote tracking branch salt myminion git.branch /path/to/repo mybranch opts='--set-upstream-to origin/mybranch' # Create new branch salt myminion git.branch /path/to/repo mybranch upstream/somebranch # Delete branch salt myminion git.branch /path/to/repo mybranch opts='-d' # Rename branch (2015.8.0 and later) salt myminion git.branch /path/to/repo newbranch opts='-m oldbranch' """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.append("branch") command.extend(_format_opts(opts)) if name is not None: command.append(name) _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) return True def checkout( cwd, rev=None, force=False, opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ Interface to `git-checkout(1)`_ cwd The path to the git checkout opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``checkout`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. rev The remote branch or revision to checkout. .. versionchanged:: 2015.8.0 Optional when using ``-b`` or ``-B`` in ``opts``. force : False Force a checkout even if there might be overwritten changes user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-checkout(1)`: http://git-scm.com/docs/git-checkout CLI Examples: .. code-block:: bash # Checking out local local revisions salt myminion git.checkout /path/to/repo somebranch user=jeff salt myminion git.checkout /path/to/repo opts='testbranch -- conf/file1 file2' salt myminion git.checkout /path/to/repo rev=origin/mybranch opts='--track' # Checking out remote revision into new branch salt myminion git.checkout /path/to/repo upstream/master opts='-b newbranch' # Checking out current revision into new branch (2015.8.0 and later) salt myminion git.checkout /path/to/repo opts='-b newbranch' """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.append("checkout") if force: command.append("--force") opts = _format_opts(opts) command.extend(opts) checkout_branch = any(x in opts for x in ("-b", "-B")) if rev is None: if not checkout_branch: raise SaltInvocationError( "'rev' argument is required unless -b or -B in opts" ) else: command.append(rev) # Checkout message goes to stderr return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, redirect_stderr=True, output_encoding=output_encoding, )["stdout"] def clone( cwd, url=None, # Remove default value once 'repository' arg is removed name=None, opts="", git_opts="", user=None, password=None, identity=None, https_user=None, https_pass=None, ignore_retcode=False, saltenv="base", output_encoding=None, ): """ Interface to `git-clone(1)`_ cwd Location of git clone .. versionchanged:: 2015.8.0 If ``name`` is passed, then the clone will be made *within* this directory. url The URL of the repository to be cloned .. versionchanged:: 2015.8.0 Argument renamed from ``repository`` to ``url`` name Optional alternate name for the top-level directory to be created by the clone .. versionadded:: 2015.8.0 opts Any additional options to add to the command line, in a single string git_opts Any additional options to add to git command itself (not the ``clone`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 identity Path to a private key to use for ssh URLs .. warning:: Unless Salt is invoked from the minion using ``salt-call``, the key(s) must be passphraseless. For greater security with passphraseless private keys, see the `sshd(8)`_ manpage for information on securing the keypair from the remote side in the ``authorized_keys`` file. .. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT .. versionchanged:: 2015.8.7 Salt will no longer attempt to use passphrase-protected keys unless invoked from the minion using ``salt-call``, to prevent blocking waiting for user input. Key can also be specified as a SaltStack file server URL, eg. salt://location/identity_file .. versionchanged:: 2016.3.0 https_user Set HTTP Basic Auth username. Only accepted for HTTPS URLs. .. versionadded:: 2015.5.0 https_pass Set HTTP Basic Auth password. Only accepted for HTTPS URLs. .. versionadded:: 2015.5.0 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 saltenv The default salt environment to pull sls files from .. versionadded:: 2016.3.1 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-clone(1)`: http://git-scm.com/docs/git-clone CLI Example: .. code-block:: bash salt myminion git.clone /path/to/repo_parent_dir git://github.com/saltstack/salt.git """ cwd = _expand_path(cwd, user) if not url: raise SaltInvocationError("Missing 'url' argument") try: url = salt.utils.url.add_http_basic_auth( url, https_user, https_pass, https_only=True ) except ValueError as exc: raise SaltInvocationError(str(exc)) command = ["git"] + _format_git_opts(git_opts) command.append("clone") command.extend(_format_opts(opts)) command.extend(["--", url]) if name is not None: command.append(name) if not os.path.exists(cwd): os.makedirs(cwd) clone_cwd = cwd else: command.append(cwd) # Use '/tmp' instead of $HOME (/root for root user) to work around # upstream git bug. See the following comment on the Salt bug tracker # for more info: # https://github.com/saltstack/salt/issues/15519#issuecomment-128531310 # On Windows, just fall back to None (runs git clone command using the # home directory as the cwd). clone_cwd = "/tmp" if not salt.utils.platform.is_windows() else None _git_run( command, cwd=clone_cwd, user=user, password=password, identity=identity, ignore_retcode=ignore_retcode, saltenv=saltenv, output_encoding=output_encoding, ) return True def commit( cwd, message, opts="", git_opts="", user=None, password=None, filename=None, ignore_retcode=False, output_encoding=None, ): """ Interface to `git-commit(1)`_ cwd The path to the git checkout message Commit message opts Any additional options to add to the command line, in a single string. These opts will be added to the end of the git command being run. .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. The ``-m`` option should not be passed here, as the commit message will be defined by the ``message`` argument. git_opts Any additional options to add to git command itself (not the ``commit`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 filename The location of the file/directory to commit, relative to ``cwd``. This argument is optional, and can be used to commit a file without first staging it. .. note:: This argument only works on files which are already tracked by the git repository. .. versionadded:: 2015.8.0 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-commit(1)`: http://git-scm.com/docs/git-commit CLI Examples: .. code-block:: bash salt myminion git.commit /path/to/repo 'The commit message' salt myminion git.commit /path/to/repo 'The commit message' filename=foo/bar.py """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.extend(["commit", "-m", message]) command.extend(_format_opts(opts)) if filename: # Add the '--' to terminate CLI args, but only if it wasn't already # passed in opts string. command.extend(["--", filename]) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def config_get( key, cwd=None, user=None, password=None, ignore_retcode=False, output_encoding=None, **kwargs, ): """ Get the value of a key in the git configuration file key The name of the configuration key to get .. versionchanged:: 2015.8.0 Argument renamed from ``setting_name`` to ``key`` cwd The path to the git checkout .. versionchanged:: 2015.8.0 Now optional if ``global`` is set to ``True`` global : False If ``True``, query the global git configuration. Otherwise, only the local git configuration will be queried. .. versionadded:: 2015.8.0 all : False If ``True``, return a list of all values set for ``key``. If the key does not exist, ``None`` will be returned. .. versionadded:: 2015.8.0 user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Examples: .. code-block:: bash salt myminion git.config_get user.name cwd=/path/to/repo salt myminion git.config_get user.email global=True salt myminion git.config_get core.gitproxy cwd=/path/to/repo all=True """ # Sanitize kwargs and make sure that no invalid ones were passed. This # allows us to accept 'all' as an argument to this function without # shadowing all(), while also not allowing unwanted arguments to be passed. all_ = kwargs.pop("all", False) result = _config_getter( "--get-all", key, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, **kwargs, ) # git config --get exits with retcode of 1 when key does not exist if result["retcode"] == 1: return None ret = result["stdout"].splitlines() if all_: return ret else: try: return ret[-1] except IndexError: # Should never happen but I'm paranoid and don't like tracebacks return "" def config_get_regexp( key, value_regex=None, cwd=None, user=None, password=None, ignore_retcode=False, output_encoding=None, **kwargs, ): r""" .. versionadded:: 2015.8.0 Get the value of a key or keys in the git configuration file using regexes for more flexible matching. The return data is a dictionary mapping keys to lists of values matching the ``value_regex``. If no values match, an empty dictionary will be returned. key Regex on which key names will be matched value_regex If specified, return all values matching this regex. The return data will be a dictionary mapping keys to lists of values matching the regex. .. important:: Only values matching the ``value_regex`` will be part of the return data. So, if ``key`` matches a multivar, then it is possible that not all of the values will be returned. To get all values set for a multivar, simply omit the ``value_regex`` argument. cwd The path to the git checkout global : False If ``True``, query the global git configuration. Otherwise, only the local git configuration will be queried. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Examples: .. code-block:: bash # Matches any values for key 'foo.bar' salt myminion git.config_get_regexp /path/to/repo foo.bar # Matches any value starting with 'baz' set for key 'foo.bar' salt myminion git.config_get_regexp /path/to/repo foo.bar 'baz.*' # Matches any key starting with 'user.' salt myminion git.config_get_regexp '^user\.' global=True """ result = _config_getter( "--get-regexp", key, value_regex=value_regex, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, **kwargs, ) # git config --get exits with retcode of 1 when key does not exist ret = {} if result["retcode"] == 1: return ret for line in result["stdout"].splitlines(): try: param, value = line.split(None, 1) except ValueError: continue ret.setdefault(param, []).append(value) return ret config_get_regex = salt.utils.functools.alias_function( config_get_regexp, "config_get_regex" ) def config_set( key, value=None, multivar=None, cwd=None, user=None, password=None, ignore_retcode=False, output_encoding=None, **kwargs, ): """ .. versionchanged:: 2015.8.0 Return the value(s) of the key being set Set a key in the git configuration file cwd The path to the git checkout. Must be an absolute path, or the word ``global`` to indicate that a global key should be set. .. versionchanged:: 2014.7.0 Made ``cwd`` argument optional if ``is_global=True`` key The name of the configuration key to set .. versionchanged:: 2015.8.0 Argument renamed from ``setting_name`` to ``key`` value The value to set for the specified key. Incompatible with the ``multivar`` argument. .. versionchanged:: 2015.8.0 Argument renamed from ``setting_value`` to ``value`` add : False Add a value to a key, creating/updating a multivar .. versionadded:: 2015.8.0 multivar Set a multivar all at once. Values can be comma-separated or passed as a Python list. Incompatible with the ``value`` argument. .. versionadded:: 2015.8.0 user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 global : False If ``True``, set a global variable output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Examples: .. code-block:: bash salt myminion git.config_set user.email me@example.com cwd=/path/to/repo salt myminion git.config_set user.email foo@bar.com global=True """ kwargs = salt.utils.args.clean_kwargs(**kwargs) add_ = kwargs.pop("add", False) global_ = kwargs.pop("global", False) if kwargs: salt.utils.args.invalid_kwargs(kwargs) if cwd is None: if not global_: raise SaltInvocationError("'cwd' argument required unless global=True") else: cwd = _expand_path(cwd, user) if all(x is not None for x in (value, multivar)): raise SaltInvocationError("Only one of 'value' and 'multivar' is permitted") if multivar is not None: if not isinstance(multivar, list): try: multivar = multivar.split(",") except AttributeError: multivar = str(multivar).split(",") else: new_multivar = [] for item in salt.utils.data.decode(multivar): if isinstance(item, str): new_multivar.append(item) else: new_multivar.append(str(item)) multivar = new_multivar command_prefix = ["git", "config"] if global_: command_prefix.append("--global") if value is not None: command = copy.copy(command_prefix) if add_: command.append("--add") else: command.append("--replace-all") command.extend([key, value]) _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) else: for idx, target in enumerate(multivar): command = copy.copy(command_prefix) if idx == 0: command.append("--replace-all") else: command.append("--add") command.extend([key, target]) _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) return config_get( key, user=user, password=password, cwd=cwd, ignore_retcode=ignore_retcode, output_encoding=output_encoding, **{"all": True, "global": global_}, ) def config_unset( key, value_regex=None, cwd=None, user=None, password=None, ignore_retcode=False, output_encoding=None, **kwargs, ): """ .. versionadded:: 2015.8.0 Unset a key in the git configuration file cwd The path to the git checkout. Must be an absolute path, or the word ``global`` to indicate that a global key should be unset. key The name of the configuration key to unset value_regex Regular expression that matches exactly one key, used to delete a single value from a multivar. Ignored if ``all`` is set to ``True``. all : False If ``True`` unset all values for a multivar. If ``False``, and ``key`` is a multivar, an error will be raised. global : False If ``True``, unset set a global variable. Otherwise, a local variable will be unset. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Example: .. code-block:: bash salt myminion git.config_unset /path/to/repo foo.bar salt myminion git.config_unset /path/to/repo foo.bar all=True """ kwargs = salt.utils.args.clean_kwargs(**kwargs) all_ = kwargs.pop("all", False) global_ = kwargs.pop("global", False) if kwargs: salt.utils.args.invalid_kwargs(kwargs) if cwd is None: if not global_: raise SaltInvocationError("'cwd' argument required unless global=True") else: cwd = _expand_path(cwd, user) command = ["git", "config"] if all_: command.append("--unset-all") else: command.append("--unset") command.extend( _which_git_config(global_, cwd, user, password, output_encoding=output_encoding) ) command.append(key) if value_regex is not None: command.append(value_regex) ret = _git_run( command, cwd=cwd if cwd != "global" else None, user=user, password=password, ignore_retcode=ignore_retcode, failhard=False, output_encoding=output_encoding, ) retcode = ret["retcode"] if retcode == 0: return True elif retcode == 1: raise CommandExecutionError("Section or key is invalid") elif retcode == 5: if ( config_get( key, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) is None ): raise CommandExecutionError(f"Key '{key}' does not exist") else: msg = f"Multiple values exist for key '{key}'" if value_regex is not None: msg += " and value_regex matches multiple values" raise CommandExecutionError(msg) elif retcode == 6: raise CommandExecutionError("The value_regex is invalid") else: msg = "Failed to unset key '{}', git config returned exit code {}".format( key, retcode ) if ret["stderr"]: msg += "; " + ret["stderr"] raise CommandExecutionError(msg) def current_branch( cwd, user=None, password=None, ignore_retcode=False, output_encoding=None ): """ Returns the current branch name of a local checkout. If HEAD is detached, return the SHA1 of the revision which is currently checked out. cwd The path to the git checkout user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Example: .. code-block:: bash salt myminion git.current_branch /path/to/repo """ cwd = _expand_path(cwd, user) command = ["git", "rev-parse", "--abbrev-ref", "HEAD"] return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def describe( cwd, rev="HEAD", user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ Returns the `git-describe(1)`_ string (or the SHA1 hash if there are no tags) for the given revision. cwd The path to the git checkout rev : HEAD The revision to describe user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-describe(1)`: http://git-scm.com/docs/git-describe CLI Examples: .. code-block:: bash salt myminion git.describe /path/to/repo salt myminion git.describe /path/to/repo develop """ cwd = _expand_path(cwd, user) command = ["git", "describe"] if LooseVersion(version(versioninfo=False)) >= LooseVersion("1.5.6"): command.append("--always") command.append(rev) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def diff( cwd, item1=None, item2=None, opts="", git_opts="", user=None, password=None, no_index=False, cached=False, paths=None, output_encoding=None, ): """ .. versionadded:: 2015.8.12,2016.3.3,2016.11.0 Interface to `git-diff(1)`_ cwd The path to the git checkout item1 and item2 Revision(s) to pass to the ``git diff`` command. One or both of these arguments may be ignored if some of the options below are set to ``True``. When ``cached`` is ``False``, and no revisions are passed to this function, then the current working tree will be compared against the index (i.e. unstaged changes). When two revisions are passed, they will be compared to each other. opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``diff`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 no_index : False When it is necessary to diff two files in the same repo against each other, and not diff two different revisions, set this option to ``True``. If this is left ``False`` in these instances, then a normal ``git diff`` will be performed against the index (i.e. unstaged changes), and files in the ``paths`` option will be used to narrow down the diff output. .. note:: Requires Git 1.5.1 or newer. Additionally, when set to ``True``, ``item1`` and ``item2`` will be ignored. cached : False If ``True``, compare staged changes to ``item1`` (if specified), otherwise compare them to the most recent commit. .. note:: ``item2`` is ignored if this option is is set to ``True``. paths File paths to pass to the ``git diff`` command. Can be passed as a comma-separated list or a Python list. output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-diff(1)`: http://git-scm.com/docs/git-diff CLI Example: .. code-block:: bash # Perform diff against the index (staging area for next commit) salt myminion git.diff /path/to/repo # Compare staged changes to the most recent commit salt myminion git.diff /path/to/repo cached=True # Compare staged changes to a specific revision salt myminion git.diff /path/to/repo mybranch cached=True # Perform diff against the most recent commit (includes staged changes) salt myminion git.diff /path/to/repo HEAD # Diff two commits salt myminion git.diff /path/to/repo abcdef1 aabbccd # Diff two commits, only showing differences in the specified paths salt myminion git.diff /path/to/repo abcdef1 aabbccd paths=path/to/file1,path/to/file2 # Diff two files with one being outside the working tree salt myminion git.diff /path/to/repo no_index=True paths=path/to/file1,/absolute/path/to/file2 """ if no_index and cached: raise CommandExecutionError( "The 'no_index' and 'cached' options cannot be used together" ) command = ["git"] + _format_git_opts(git_opts) command.append("diff") command.extend(_format_opts(opts)) if paths is not None and not isinstance(paths, (list, tuple)): try: paths = paths.split(",") except AttributeError: paths = str(paths).split(",") ignore_retcode = False failhard = True if no_index: if LooseVersion(version(versioninfo=False)) < LooseVersion("1.5.1"): raise CommandExecutionError( "The 'no_index' option is only supported in Git 1.5.1 and newer" ) ignore_retcode = True failhard = False command.append("--no-index") for value in [x for x in (item1, item2) if x]: log.warning( "Revision '%s' ignored in git diff, as revisions cannot be " "used when no_index=True", value, ) elif cached: command.append("--cached") if item1: command.append(item1) if item2: log.warning( "Second revision '%s' ignored in git diff, at most one " "revision is considered when cached=True", item2, ) else: for value in [x for x in (item1, item2) if x]: command.append(value) if paths: command.append("--") command.extend(paths) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, failhard=failhard, redirect_stderr=True, output_encoding=output_encoding, )["stdout"] def discard_local_changes( cwd, path=".", user=None, password=None, ignore_retcode=False, output_encoding=None ): """ .. versionadded:: 2019.2.0 Runs a ``git checkout -- <path>`` from the directory specified by ``cwd``. cwd The path to the git checkout path path relative to cwd (defaults to ``.``) user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. CLI Example: .. code-block:: bash salt myminion git.discard_local_changes /path/to/repo salt myminion git.discard_local_changes /path/to/repo path=foo """ cwd = _expand_path(cwd, user) command = ["git", "checkout", "--", path] # Checkout message goes to stderr return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, redirect_stderr=True, output_encoding=output_encoding, )["stdout"] def fetch( cwd, remote=None, force=False, refspecs=None, opts="", git_opts="", user=None, password=None, identity=None, ignore_retcode=False, saltenv="base", output_encoding=None, ): """ .. versionchanged:: 2015.8.2 Return data is now a dictionary containing information on branches and tags that were added/updated Interface to `git-fetch(1)`_ cwd The path to the git checkout remote Optional remote name to fetch. If not passed, then git will use its default behavior (as detailed in `git-fetch(1)`_). .. versionadded:: 2015.8.0 force Force the fetch even when it is not a fast-forward. .. versionadded:: 2015.8.0 refspecs Override the refspec(s) configured for the remote with this argument. Multiple refspecs can be passed, comma-separated. .. versionadded:: 2015.8.0 opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``fetch`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 identity Path to a private key to use for ssh URLs .. warning:: Unless Salt is invoked from the minion using ``salt-call``, the key(s) must be passphraseless. For greater security with passphraseless private keys, see the `sshd(8)`_ manpage for information on securing the keypair from the remote side in the ``authorized_keys`` file. .. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT .. versionchanged:: 2015.8.7 Salt will no longer attempt to use passphrase-protected keys unless invoked from the minion using ``salt-call``, to prevent blocking waiting for user input. Key can also be specified as a SaltStack file server URL, eg. salt://location/identity_file .. versionchanged:: 2016.3.0 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 saltenv The default salt environment to pull sls files from .. versionadded:: 2016.3.1 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-fetch(1)`: http://git-scm.com/docs/git-fetch CLI Example: .. code-block:: bash salt myminion git.fetch /path/to/repo upstream salt myminion git.fetch /path/to/repo identity=/root/.ssh/id_rsa """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.append("fetch") if force: command.append("--force") command.extend([x for x in _format_opts(opts) if x not in ("-f", "--force")]) if remote: command.append(remote) if refspecs is not None: if not isinstance(refspecs, (list, tuple)): try: refspecs = refspecs.split(",") except AttributeError: refspecs = str(refspecs).split(",") refspecs = salt.utils.data.stringify(refspecs) command.extend(refspecs) output = _git_run( command, cwd=cwd, user=user, password=password, identity=identity, ignore_retcode=ignore_retcode, redirect_stderr=True, saltenv=saltenv, output_encoding=output_encoding, )["stdout"] update_re = re.compile( r"[\s*]*(?:([0-9a-f]+)\.\.([0-9a-f]+)|" r"\[(?:new (tag|branch)|tag update)\])\s+(.+)->" ) ret = {} for line in salt.utils.itertools.split(output, "\n"): match = update_re.match(line) if match: old_sha, new_sha, new_ref_type, ref_name = match.groups() ref_name = ref_name.rstrip() if new_ref_type is not None: # ref is a new tag/branch ref_key = "new tags" if new_ref_type == "tag" else "new branches" ret.setdefault(ref_key, []).append(ref_name) elif old_sha is not None: # ref is a branch update ret.setdefault("updated branches", {})[ref_name] = { "old": old_sha, "new": new_sha, } else: # ref is an updated tag ret.setdefault("updated tags", []).append(ref_name) return ret def init( cwd, bare=False, template=None, separate_git_dir=None, shared=None, opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ Interface to `git-init(1)`_ cwd The path to the directory to be initialized bare : False If ``True``, init a bare repository .. versionadded:: 2015.8.0 template Set this argument to specify an alternate `template directory`_ .. versionadded:: 2015.8.0 separate_git_dir Set this argument to specify an alternate ``$GIT_DIR`` .. versionadded:: 2015.8.0 shared Set sharing permissions on git repo. See `git-init(1)`_ for more details. .. versionadded:: 2015.8.0 opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``init`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-init(1)`: http://git-scm.com/docs/git-init .. _`template directory`: http://git-scm.com/docs/git-init#_template_directory CLI Examples: .. code-block:: bash salt myminion git.init /path/to/repo # Init a bare repo (before 2015.8.0) salt myminion git.init /path/to/bare/repo.git opts='--bare' # Init a bare repo (2015.8.0 and later) salt myminion git.init /path/to/bare/repo.git bare=True """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.append("init") if bare: command.append("--bare") if template is not None: command.append(f"--template={template}") if separate_git_dir is not None: command.append(f"--separate-git-dir={separate_git_dir}") if shared is not None: if isinstance(shared, int) and not isinstance(shared, bool): shared = "0" + str(shared) elif not isinstance(shared, str): # Using lower here because booleans would be capitalized when # converted to a string. shared = str(shared).lower() command.append(f"--shared={shared}") command.extend(_format_opts(opts)) command.append(cwd) return _git_run( command, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def is_worktree(cwd, user=None, password=None, output_encoding=None): """ .. versionadded:: 2015.8.0 This function will attempt to determine if ``cwd`` is part of a worktree by checking its ``.git`` to see if it is a file containing a reference to another gitdir. cwd path to the worktree to be removed user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Example: .. code-block:: bash salt myminion git.is_worktree /path/to/repo """ cwd = _expand_path(cwd, user) try: toplevel = _get_toplevel( cwd, user=user, password=password, output_encoding=output_encoding ) except CommandExecutionError: return False gitdir = os.path.join(toplevel, ".git") try: with salt.utils.files.fopen(gitdir, "r") as fp_: for line in fp_: line = salt.utils.stringutils.to_unicode(line) try: label, path = line.split(None, 1) except ValueError: return False else: # This file should only contain a single line. However, we # loop here to handle the corner case where .git is a large # binary file, so that we do not read the entire file into # memory at once. We'll hit a return statement before this # loop enters a second iteration. if label == "gitdir:" and os.path.isabs(path): return True else: return False except OSError: return False return False def list_branches( cwd, remote=False, user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ .. versionadded:: 2015.8.0 Return a list of branches cwd The path to the git checkout remote : False If ``True``, list remote branches. Otherwise, local branches will be listed. .. warning:: This option will only return remote branches of which the local checkout is aware, use :py:func:`git.fetch <salt.modules.git.fetch>` to update remotes. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Examples: .. code-block:: bash salt myminion git.list_branches /path/to/repo salt myminion git.list_branches /path/to/repo remote=True """ cwd = _expand_path(cwd, user) command = [ "git", "for-each-ref", "--format", "%(refname:short)", "refs/{}/".format("heads" if not remote else "remotes"), ] return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"].splitlines() def list_tags( cwd, user=None, password=None, ignore_retcode=False, output_encoding=None ): """ .. versionadded:: 2015.8.0 Return a list of tags cwd The path to the git checkout user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Examples: .. code-block:: bash salt myminion git.list_tags /path/to/repo """ cwd = _expand_path(cwd, user) command = ["git", "for-each-ref", "--format", "%(refname:short)", "refs/tags/"] return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"].splitlines() def list_worktrees( cwd, stale=False, user=None, password=None, output_encoding=None, **kwargs ): """ .. versionadded:: 2015.8.0 Returns information on worktrees .. versionchanged:: 2015.8.4 Version 2.7.0 added the ``list`` subcommand to `git-worktree(1)`_ which provides a lot of additional information. The return data has been changed to include this information, even for pre-2.7.0 versions of git. In addition, if a worktree has a detached head, then any tags which point to the worktree's HEAD will be included in the return data. .. note:: By default, only worktrees for which the worktree directory is still present are returned, but this can be changed using the ``all`` and ``stale`` arguments (described below). cwd The path to the git checkout user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 all : False If ``True``, then return all worktrees tracked under $GIT_DIR/worktrees, including ones for which the gitdir is no longer present. stale : False If ``True``, return *only* worktrees whose gitdir is no longer present. .. note:: Only one of ``all`` and ``stale`` can be set to ``True``. output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-worktree(1)`: http://git-scm.com/docs/git-worktree CLI Examples: .. code-block:: bash salt myminion git.list_worktrees /path/to/repo salt myminion git.list_worktrees /path/to/repo all=True salt myminion git.list_worktrees /path/to/repo stale=True """ if not _check_worktree_support(failhard=True): return {} cwd = _expand_path(cwd, user) kwargs = salt.utils.args.clean_kwargs(**kwargs) all_ = kwargs.pop("all", False) if kwargs: salt.utils.args.invalid_kwargs(kwargs) if all_ and stale: raise CommandExecutionError("'all' and 'stale' cannot both be set to True") def _git_tag_points_at(cwd, rev, user=None, password=None, output_encoding=None): """ Get any tags that point at a """ return _git_run( ["git", "tag", "--points-at", rev], cwd=cwd, user=user, password=password, output_encoding=output_encoding, )["stdout"].splitlines() def _desired(is_stale, all_, stale): """ Common logic to determine whether or not to include the worktree info in the return data. """ if is_stale: if not all_ and not stale: # Stale worktrees are not desired, skip this one return False else: if stale: # Only stale worktrees are desired, skip this one return False return True def _duplicate_worktree_path(path): """ Log errors to the minion log notifying of duplicate worktree paths. These should not be there, but may show up due to a bug in git 2.7.0. """ log.error( "git.worktree: Duplicate worktree path %s. This may be caused by " "a known issue in git 2.7.0 (see " "http://permalink.gmane.org/gmane.comp.version-control.git/283998)", path, ) tracked_data_points = ("worktree", "HEAD", "branch") ret = {} git_version = LooseVersion(version(versioninfo=False)) has_native_list_subcommand = git_version >= LooseVersion("2.7.0") if has_native_list_subcommand: out = _git_run( ["git", "worktree", "list", "--porcelain"], cwd=cwd, user=user, password=password, output_encoding=output_encoding, ) if out["retcode"] != 0: msg = "Failed to list worktrees" if out["stderr"]: msg += ": {}".format(out["stderr"]) raise CommandExecutionError(msg) def _untracked_item(line): """ Log a warning """ log.warning("git.worktree: Untracked line item '%s'", line) for individual_worktree in salt.utils.itertools.split( out["stdout"].strip(), "\n\n" ): # Initialize the dict where we're storing the tracked data points worktree_data = {x: "" for x in tracked_data_points} for line in salt.utils.itertools.split(individual_worktree, "\n"): try: type_, value = line.strip().split(None, 1) except ValueError: if line == "detached": type_ = "branch" value = "detached" else: _untracked_item(line) continue if type_ not in tracked_data_points: _untracked_item(line) continue if worktree_data[type_]: log.error( "git.worktree: Unexpected duplicate %s entry '%s', skipping", type_, line, ) continue worktree_data[type_] = value # Check for missing data points missing = [x for x in tracked_data_points if not worktree_data[x]] if missing: log.error( "git.worktree: Incomplete worktree data, missing the " "following information: %s. Full data below:\n%s", ", ".join(missing), individual_worktree, ) continue worktree_is_stale = not os.path.isdir(worktree_data["worktree"]) if not _desired(worktree_is_stale, all_, stale): continue if worktree_data["worktree"] in ret: _duplicate_worktree_path(worktree_data["worktree"]) wt_ptr = ret.setdefault(worktree_data["worktree"], {}) wt_ptr["stale"] = worktree_is_stale wt_ptr["HEAD"] = worktree_data["HEAD"] wt_ptr["detached"] = worktree_data["branch"] == "detached" if wt_ptr["detached"]: wt_ptr["branch"] = None # Check to see if HEAD points at a tag tags_found = _git_tag_points_at( cwd, wt_ptr["HEAD"], user=user, password=password, output_encoding=output_encoding, ) if tags_found: wt_ptr["tags"] = tags_found else: wt_ptr["branch"] = worktree_data["branch"].replace("refs/heads/", "", 1) return ret else: toplevel = _get_toplevel( cwd, user=user, password=password, output_encoding=output_encoding ) try: worktree_root = rev_parse( cwd, opts=["--git-path", "worktrees"], user=user, password=password, output_encoding=output_encoding, ) except CommandExecutionError as exc: msg = "Failed to find worktree location for " + cwd log.error(msg, exc_info_on_loglevel=logging.DEBUG) raise CommandExecutionError(msg) if worktree_root.startswith(".git"): worktree_root = os.path.join(cwd, worktree_root) if not os.path.isdir(worktree_root): raise CommandExecutionError( f"Worktree admin directory {worktree_root} not present" ) def _read_file(path): """ Return contents of a single line file with EOF newline stripped """ try: with salt.utils.files.fopen(path, "r") as fp_: for line in fp_: ret = salt.utils.stringutils.to_unicode(line).strip() # Ignore other lines, if they exist (which they # shouldn't) break return ret except OSError as exc: # Raise a CommandExecutionError salt.utils.files.process_read_exception(exc, path) for worktree_name in os.listdir(worktree_root): admin_dir = os.path.join(worktree_root, worktree_name) gitdir_file = os.path.join(admin_dir, "gitdir") head_file = os.path.join(admin_dir, "HEAD") wt_loc = _read_file(gitdir_file) head_ref = _read_file(head_file) if not os.path.isabs(wt_loc): log.error( "Non-absolute path found in %s. If git 2.7.0 was " "installed and then downgraded, this was likely caused " "by a known issue in git 2.7.0. See " "http://permalink.gmane.org/gmane.comp.version-control" ".git/283998 for more information.", gitdir_file, ) # Emulate what 'git worktree list' does under-the-hood, and # that is using the toplevel directory. It will still give # inaccurate results, but will avoid a traceback. wt_loc = toplevel if wt_loc.endswith("/.git"): wt_loc = wt_loc[:-5] worktree_is_stale = not os.path.isdir(wt_loc) if not _desired(worktree_is_stale, all_, stale): continue if wt_loc in ret: _duplicate_worktree_path(wt_loc) if head_ref.startswith("ref: "): head_ref = head_ref.split(None, 1)[-1] wt_branch = head_ref.replace("refs/heads/", "", 1) wt_head = rev_parse( cwd, rev=head_ref, user=user, password=password, output_encoding=output_encoding, ) wt_detached = False else: wt_branch = None wt_head = head_ref wt_detached = True wt_ptr = ret.setdefault(wt_loc, {}) wt_ptr["stale"] = worktree_is_stale wt_ptr["branch"] = wt_branch wt_ptr["HEAD"] = wt_head wt_ptr["detached"] = wt_detached # Check to see if HEAD points at a tag if wt_detached: tags_found = _git_tag_points_at( cwd, wt_head, user=user, password=password, output_encoding=output_encoding, ) if tags_found: wt_ptr["tags"] = tags_found return ret def ls_remote( cwd=None, remote="origin", ref=None, opts="", git_opts="", user=None, password=None, identity=None, https_user=None, https_pass=None, ignore_retcode=False, output_encoding=None, saltenv="base", ): """ Interface to `git-ls-remote(1)`_. Returns the upstream hash for a remote reference. cwd The path to the git checkout. Optional (and ignored if present) when ``remote`` is set to a URL instead of a remote name. remote : origin The name of the remote to query. Can be the name of a git remote (which exists in the git checkout defined by the ``cwd`` parameter), or the URL of a remote repository. .. versionchanged:: 2015.8.0 Argument renamed from ``repository`` to ``remote`` ref The name of the ref to query. Optional, if not specified, all refs are returned. Can be a branch or tag name, or the full name of the reference (for example, to get the hash for a Github pull request number 1234, ``ref`` can be set to ``refs/pull/1234/head`` .. versionchanged:: 2015.8.0 Argument renamed from ``branch`` to ``ref`` .. versionchanged:: 2015.8.4 Defaults to returning all refs instead of master. opts Any additional options to add to the command line, in a single string .. versionadded:: 2015.8.0 git_opts Any additional options to add to git command itself (not the ``ls-remote`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 identity Path to a private key to use for ssh URLs .. warning:: Unless Salt is invoked from the minion using ``salt-call``, the key(s) must be passphraseless. For greater security with passphraseless private keys, see the `sshd(8)`_ manpage for information on securing the keypair from the remote side in the ``authorized_keys`` file. .. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT .. versionchanged:: 2015.8.7 Salt will no longer attempt to use passphrase-protected keys unless invoked from the minion using ``salt-call``, to prevent blocking waiting for user input. Key can also be specified as a SaltStack file server URL, eg. salt://location/identity_file .. versionchanged:: 2016.3.0 https_user Set HTTP Basic Auth username. Only accepted for HTTPS URLs. .. versionadded:: 2015.5.0 https_pass Set HTTP Basic Auth password. Only accepted for HTTPS URLs. .. versionadded:: 2015.5.0 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 saltenv The default salt environment to pull sls files from .. versionadded:: 2016.3.1 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-ls-remote(1)`: http://git-scm.com/docs/git-ls-remote CLI Example: .. code-block:: bash salt myminion git.ls_remote /path/to/repo origin master salt myminion git.ls_remote remote=https://mydomain.tld/repo.git ref=mytag opts='--tags' """ if cwd is not None: cwd = _expand_path(cwd, user) try: remote = salt.utils.url.add_http_basic_auth( remote, https_user, https_pass, https_only=True ) except ValueError as exc: raise SaltInvocationError(str(exc)) command = ["git"] + _format_git_opts(git_opts) command.append("ls-remote") command.extend(_format_opts(opts)) command.append(remote) if ref: command.append(ref) output = _git_run( command, cwd=cwd, user=user, password=password, identity=identity, ignore_retcode=ignore_retcode, saltenv=saltenv, output_encoding=output_encoding, )["stdout"] ret = {} for line in output.splitlines(): try: ref_sha1, ref_name = line.split(None, 1) except IndexError: continue ret[ref_name] = ref_sha1 return ret def merge( cwd, rev=None, opts="", git_opts="", user=None, password=None, identity=None, ignore_retcode=False, output_encoding=None, **kwargs, ): """ Interface to `git-merge(1)`_ cwd The path to the git checkout rev Revision to merge into the current branch. If not specified, the remote tracking branch will be merged. .. versionadded:: 2015.8.0 opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``merge`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 identity Path to a private key to use for ssh URLs. Salt will not attempt to use passphrase-protected keys unless invoked from the minion using ``salt-call``, to prevent blocking waiting for user input. Key can also be specified as a SaltStack file server URL, eg. ``salt://location/identity_file``. .. note:: For greater security with passphraseless private keys, see the `sshd(8)`_ manpage for information on securing the keypair from the remote side in the ``authorized_keys`` file. .. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT .. versionadded:: 2018.3.5,2019.2.1,3000 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-merge(1)`: http://git-scm.com/docs/git-merge CLI Example: .. code-block:: bash # Fetch first... salt myminion git.fetch /path/to/repo # ... then merge the remote tracking branch salt myminion git.merge /path/to/repo # .. or merge another rev salt myminion git.merge /path/to/repo rev=upstream/foo """ kwargs = salt.utils.args.clean_kwargs(**kwargs) if kwargs: salt.utils.args.invalid_kwargs(kwargs) cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.append("merge") command.extend(_format_opts(opts)) if rev: command.append(rev) return _git_run( command, cwd=cwd, user=user, password=password, identity=identity, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def merge_base( cwd, refs=None, octopus=False, is_ancestor=False, independent=False, fork_point=None, opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, **kwargs, ): """ .. versionadded:: 2015.8.0 Interface to `git-merge-base(1)`_. cwd The path to the git checkout refs Any refs/commits to check for a merge base. Can be passed as a comma-separated list or a Python list. all : False Return a list of all matching merge bases. Not compatible with any of the below options except for ``octopus``. octopus : False If ``True``, then this function will determine the best common ancestors of all specified commits, in preparation for an n-way merge. See here_ for a description of how these bases are determined. Set ``all`` to ``True`` with this option to return all computed merge bases, otherwise only the "best" will be returned. is_ancestor : False If ``True``, then instead of returning the merge base, return a boolean telling whether or not the first commit is an ancestor of the second commit. .. note:: This option requires two commits to be passed. .. versionchanged:: 2015.8.2 Works properly in git versions older than 1.8.0, where the ``--is-ancestor`` CLI option is not present. independent : False If ``True``, this function will return the IDs of the refs/commits passed which cannot be reached by another commit. fork_point If passed, then this function will return the commit where the commit diverged from the ref specified by ``fork_point``. If no fork point is found, ``None`` is returned. .. note:: At most one commit is permitted to be passed if a ``fork_point`` is specified. If no commits are passed, then ``HEAD`` is assumed. opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. This option should not be necessary unless new CLI arguments are added to `git-merge-base(1)`_ and are not yet supported in Salt. git_opts Any additional options to add to git command itself (not the ``merge-base`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False if ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-merge-base(1)`: http://git-scm.com/docs/git-merge-base .. _here: http://git-scm.com/docs/git-merge-base#_discussion CLI Examples: .. code-block:: bash salt myminion git.merge_base /path/to/repo HEAD upstream/mybranch salt myminion git.merge_base /path/to/repo 8f2e542,4ad8cab,cdc9886 octopus=True salt myminion git.merge_base /path/to/repo refs=8f2e542,4ad8cab,cdc9886 independent=True salt myminion git.merge_base /path/to/repo refs=8f2e542,4ad8cab is_ancestor=True salt myminion git.merge_base /path/to/repo fork_point=upstream/master salt myminion git.merge_base /path/to/repo refs=mybranch fork_point=upstream/master """ cwd = _expand_path(cwd, user) kwargs = salt.utils.args.clean_kwargs(**kwargs) all_ = kwargs.pop("all", False) if kwargs: salt.utils.args.invalid_kwargs(kwargs) if all_ and (independent or is_ancestor or fork_point): raise SaltInvocationError( "The 'all' argument is not compatible with 'independent', " "'is_ancestor', or 'fork_point'" ) if refs is None: refs = [] elif not isinstance(refs, (list, tuple)): refs = [x.strip() for x in str(refs).split(",")] mutually_exclusive_count = len( [x for x in (octopus, independent, is_ancestor, fork_point) if x] ) if mutually_exclusive_count > 1: raise SaltInvocationError( "Only one of 'octopus', 'independent', 'is_ancestor', and " "'fork_point' is permitted" ) elif is_ancestor: if len(refs) != 2: raise SaltInvocationError( "Two refs/commits are required if 'is_ancestor' is True" ) elif fork_point: if len(refs) > 1: raise SaltInvocationError( "At most one ref/commit can be passed if 'fork_point' is specified" ) elif not refs: refs = ["HEAD"] if is_ancestor: if LooseVersion(version(versioninfo=False)) < LooseVersion("1.8.0"): # Pre 1.8.0 git doesn't have --is-ancestor, so the logic here is a # little different. First we need to resolve the first ref to a # full SHA1, and then if running git merge-base on both commits # returns an identical commit to the resolved first ref, we know # that the first ref is an ancestor of the second ref. first_commit = rev_parse( cwd, rev=refs[0], opts=["--verify"], user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) return ( merge_base( cwd, refs=refs, is_ancestor=False, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) == first_commit ) command = ["git"] + _format_git_opts(git_opts) command.append("merge-base") command.extend(_format_opts(opts)) if all_: command.append("--all") if octopus: command.append("--octopus") elif is_ancestor: command.append("--is-ancestor") elif independent: command.append("--independent") elif fork_point: command.extend(["--fork-point", fork_point]) command.extend(refs) result = _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, failhard=False if is_ancestor else True, output_encoding=output_encoding, ) if is_ancestor: return result["retcode"] == 0 all_bases = result["stdout"].splitlines() if all_: return all_bases return all_bases[0] def merge_tree( cwd, ref1, ref2, base=None, user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ .. versionadded:: 2015.8.0 Interface to `git-merge-tree(1)`_, shows the merge results and conflicts from a 3-way merge without touching the index. cwd The path to the git checkout ref1 First ref/commit to compare ref2 Second ref/commit to compare base The base tree to use for the 3-way-merge. If not provided, then :py:func:`git.merge_base <salt.modules.git.merge_base>` will be invoked on ``ref1`` and ``ref2`` to determine the merge base to use. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False if ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-merge-tree(1)`: http://git-scm.com/docs/git-merge-tree CLI Examples: .. code-block:: bash salt myminion git.merge_tree /path/to/repo HEAD upstream/dev salt myminion git.merge_tree /path/to/repo HEAD upstream/dev base=aaf3c3d """ cwd = _expand_path(cwd, user) command = ["git", "merge-tree"] if base is None: try: base = merge_base(cwd, refs=[ref1, ref2], output_encoding=output_encoding) except (SaltInvocationError, CommandExecutionError): raise CommandExecutionError( f"Unable to determine merge base for {ref1} and {ref2}" ) command.extend([base, ref1, ref2]) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def pull( cwd, opts="", git_opts="", user=None, password=None, identity=None, ignore_retcode=False, saltenv="base", output_encoding=None, ): """ Interface to `git-pull(1)`_ cwd The path to the git checkout opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``pull`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 identity Path to a private key to use for ssh URLs .. warning:: Unless Salt is invoked from the minion using ``salt-call``, the key(s) must be passphraseless. For greater security with passphraseless private keys, see the `sshd(8)`_ manpage for information on securing the keypair from the remote side in the ``authorized_keys`` file. .. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT .. versionchanged:: 2015.8.7 Salt will no longer attempt to use passphrase-protected keys unless invoked from the minion using ``salt-call``, to prevent blocking waiting for user input. Key can also be specified as a SaltStack file server URL, eg. salt://location/identity_file .. versionchanged:: 2016.3.0 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 saltenv The default salt environment to pull sls files from .. versionadded:: 2016.3.1 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-pull(1)`: http://git-scm.com/docs/git-pull CLI Example: .. code-block:: bash salt myminion git.pull /path/to/repo opts='--rebase origin master' """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.append("pull") command.extend(_format_opts(opts)) return _git_run( command, cwd=cwd, user=user, password=password, identity=identity, ignore_retcode=ignore_retcode, saltenv=saltenv, output_encoding=output_encoding, )["stdout"] def push( cwd, remote=None, ref=None, opts="", git_opts="", user=None, password=None, identity=None, ignore_retcode=False, saltenv="base", output_encoding=None, **kwargs, ): """ Interface to `git-push(1)`_ cwd The path to the git checkout remote Name of the remote to which the ref should being pushed .. versionadded:: 2015.8.0 ref : master Name of the ref to push .. note:: Being a refspec_, this argument can include a colon to define local and remote ref names. opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``push`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 identity Path to a private key to use for ssh URLs .. warning:: Unless Salt is invoked from the minion using ``salt-call``, the key(s) must be passphraseless. For greater security with passphraseless private keys, see the `sshd(8)`_ manpage for information on securing the keypair from the remote side in the ``authorized_keys`` file. .. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT .. versionchanged:: 2015.8.7 Salt will no longer attempt to use passphrase-protected keys unless invoked from the minion using ``salt-call``, to prevent blocking waiting for user input. Key can also be specified as a SaltStack file server URL, eg. salt://location/identity_file .. versionchanged:: 2016.3.0 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 saltenv The default salt environment to pull sls files from .. versionadded:: 2016.3.1 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-push(1)`: http://git-scm.com/docs/git-push .. _refspec: http://git-scm.com/book/en/v2/Git-Internals-The-Refspec CLI Example: .. code-block:: bash # Push master as origin/master salt myminion git.push /path/to/repo origin master # Push issue21 as upstream/develop salt myminion git.push /path/to/repo upstream issue21:develop # Delete remote branch 'upstream/temp' salt myminion git.push /path/to/repo upstream :temp """ kwargs = salt.utils.args.clean_kwargs(**kwargs) if kwargs: salt.utils.args.invalid_kwargs(kwargs) cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.append("push") command.extend(_format_opts(opts)) command.extend([remote, ref]) return _git_run( command, cwd=cwd, user=user, password=password, identity=identity, ignore_retcode=ignore_retcode, saltenv=saltenv, output_encoding=output_encoding, )["stdout"] def rebase( cwd, rev="master", opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ Interface to `git-rebase(1)`_ cwd The path to the git checkout rev : master The revision to rebase onto the current branch opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``rebase`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-rebase(1)`: http://git-scm.com/docs/git-rebase CLI Example: .. code-block:: bash salt myminion git.rebase /path/to/repo master salt myminion git.rebase /path/to/repo 'origin master' salt myminion git.rebase /path/to/repo origin/master opts='--onto newbranch' """ cwd = _expand_path(cwd, user) opts = _format_opts(opts) if any(x for x in opts if x in ("-i", "--interactive")): raise SaltInvocationError("Interactive rebases are not supported") command = ["git"] + _format_git_opts(git_opts) command.append("rebase") command.extend(opts) if not isinstance(rev, str): rev = str(rev) command.extend(salt.utils.args.shlex_split(rev)) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def remote_get( cwd, remote="origin", user=None, password=None, redact_auth=True, ignore_retcode=False, output_encoding=None, ): """ Get the fetch and push URL for a specific remote cwd The path to the git checkout remote : origin Name of the remote to query user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 redact_auth : True Set to ``False`` to include the username/password if the remote uses HTTPS Basic Auth. Otherwise, this information will be redacted. .. warning:: Setting this to ``False`` will not only reveal any HTTPS Basic Auth that is configured, but the return data will also be written to the job cache. When possible, it is recommended to use SSH for authentication. .. versionadded:: 2015.5.6 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Examples: .. code-block:: bash salt myminion git.remote_get /path/to/repo salt myminion git.remote_get /path/to/repo upstream """ cwd = _expand_path(cwd, user) all_remotes = remotes( cwd, user=user, password=password, redact_auth=redact_auth, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) if remote not in all_remotes: raise CommandExecutionError( f"Remote '{remote}' not present in git checkout located at {cwd}" ) return all_remotes[remote] def remote_refs( url, heads=False, tags=False, user=None, password=None, identity=None, https_user=None, https_pass=None, ignore_retcode=False, output_encoding=None, saltenv="base", **kwargs, ): """ .. versionadded:: 2015.8.0 Return the remote refs for the specified URL by running ``git ls-remote``. url URL of the remote repository filter Optionally provide a ref name to ``git ls-remote``. This can be useful to make this function run faster on repositories with many branches/tags. .. versionadded:: 2019.2.0 heads : False Restrict output to heads. Can be combined with ``tags``. tags : False Restrict output to tags. Can be combined with ``heads``. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 identity Path to a private key to use for ssh URLs .. warning:: Unless Salt is invoked from the minion using ``salt-call``, the key(s) must be passphraseless. For greater security with passphraseless private keys, see the `sshd(8)`_ manpage for information on securing the keypair from the remote side in the ``authorized_keys`` file. .. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT .. versionchanged:: 2015.8.7 Salt will no longer attempt to use passphrase-protected keys unless invoked from the minion using ``salt-call``, to prevent blocking waiting for user input. Key can also be specified as a SaltStack file server URL, eg. salt://location/identity_file .. versionchanged:: 2016.3.0 https_user Set HTTP Basic Auth username. Only accepted for HTTPS URLs. https_pass Set HTTP Basic Auth password. Only accepted for HTTPS URLs. ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. saltenv The default salt environment to pull sls files from .. versionadded:: 2016.3.1 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Example: .. code-block:: bash salt myminion git.remote_refs https://github.com/saltstack/salt.git salt myminion git.remote_refs https://github.com/saltstack/salt.git filter=develop """ kwargs = salt.utils.args.clean_kwargs(**kwargs) filter_ = kwargs.pop("filter", None) if kwargs: salt.utils.args.invalid_kwargs(kwargs) command = ["git", "ls-remote"] if heads: command.append("--heads") if tags: command.append("--tags") try: command.append( salt.utils.url.add_http_basic_auth( url, https_user, https_pass, https_only=True ) ) except ValueError as exc: raise SaltInvocationError(str(exc)) if filter_: command.append(filter_) output = _git_run( command, user=user, password=password, identity=identity, ignore_retcode=ignore_retcode, saltenv=saltenv, output_encoding=output_encoding, )["stdout"] ret = {} for line in salt.utils.itertools.split(output, "\n"): try: sha1_hash, ref_name = line.split(None, 1) except ValueError: continue ret[ref_name] = sha1_hash return ret def remote_set( cwd, url, remote="origin", user=None, password=None, https_user=None, https_pass=None, push_url=None, push_https_user=None, push_https_pass=None, ignore_retcode=False, output_encoding=None, ): """ cwd The path to the git checkout url Remote URL to set remote : origin Name of the remote to set push_url If unset, the push URL will be identical to the fetch URL. .. versionadded:: 2015.8.0 user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 https_user Set HTTP Basic Auth username. Only accepted for HTTPS URLs. .. versionadded:: 2015.5.0 https_pass Set HTTP Basic Auth password. Only accepted for HTTPS URLs. .. versionadded:: 2015.5.0 push_https_user Set HTTP Basic Auth user for ``push_url``. Ignored if ``push_url`` is unset. Only accepted for HTTPS URLs. .. versionadded:: 2015.8.0 push_https_pass Set HTTP Basic Auth password for ``push_url``. Ignored if ``push_url`` is unset. Only accepted for HTTPS URLs. .. versionadded:: 2015.8.0 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Examples: .. code-block:: bash salt myminion git.remote_set /path/to/repo git@github.com:user/repo.git salt myminion git.remote_set /path/to/repo git@github.com:user/repo.git remote=upstream salt myminion git.remote_set /path/to/repo https://github.com/user/repo.git remote=upstream push_url=git@github.com:user/repo.git """ # Check if remote exists if remote in remotes( cwd, user=user, password=password, output_encoding=output_encoding ): log.debug( "Remote '%s' already exists in git checkout located at %s, " "removing so it can be re-added", remote, cwd, ) command = ["git", "remote", "rm", remote] _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) # Add remote try: url = salt.utils.url.add_http_basic_auth( url, https_user, https_pass, https_only=True ) except ValueError as exc: raise SaltInvocationError(str(exc)) command = ["git", "remote", "add", remote, url] _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) if push_url: if not isinstance(push_url, str): push_url = str(push_url) try: push_url = salt.utils.url.add_http_basic_auth( push_url, push_https_user, push_https_pass, https_only=True ) except ValueError as exc: raise SaltInvocationError(str(exc)) command = ["git", "remote", "set-url", "--push", remote, push_url] _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) return remote_get( cwd=cwd, remote=remote, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) def remotes( cwd, user=None, password=None, redact_auth=True, ignore_retcode=False, output_encoding=None, ): """ Get fetch and push URLs for each remote in a git checkout cwd The path to the git checkout user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 redact_auth : True Set to ``False`` to include the username/password for authenticated remotes in the return data. Otherwise, this information will be redacted. .. warning:: Setting this to ``False`` will not only reveal any HTTPS Basic Auth that is configured, but the return data will also be written to the job cache. When possible, it is recommended to use SSH for authentication. .. versionadded:: 2015.5.6 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Example: .. code-block:: bash salt myminion git.remotes /path/to/repo """ cwd = _expand_path(cwd, user) command = ["git", "remote", "--verbose"] ret = {} output = _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] for remote_line in salt.utils.itertools.split(output, "\n"): try: remote, remote_info = remote_line.split(None, 1) except ValueError: continue try: remote_url, action = remote_info.rsplit(None, 1) except ValueError: continue # Remove parenthesis action = action.lstrip("(").rstrip(")").lower() if action not in ("fetch", "push"): log.warning( "Unknown action '%s' for remote '%s' in git checkout located in %s", action, remote, cwd, ) continue if redact_auth: remote_url = salt.utils.url.redact_http_basic_auth(remote_url) ret.setdefault(remote, {})[action] = remote_url return ret def reset( cwd, opts="", git_opts="", user=None, password=None, identity=None, ignore_retcode=False, output_encoding=None, ): """ Interface to `git-reset(1)`_, returns the stdout from the git command cwd The path to the git checkout opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``reset`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 identity Path to a private key to use for ssh URLs. Salt will not attempt to use passphrase-protected keys unless invoked from the minion using ``salt-call``, to prevent blocking waiting for user input. Key can also be specified as a SaltStack file server URL, eg. ``salt://location/identity_file``. .. note:: For greater security with passphraseless private keys, see the `sshd(8)`_ manpage for information on securing the keypair from the remote side in the ``authorized_keys`` file. .. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT .. versionadded:: 2018.3.5,2019.2.1,3000 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-reset(1)`: http://git-scm.com/docs/git-reset CLI Examples: .. code-block:: bash # Soft reset to a specific commit ID salt myminion git.reset /path/to/repo ac3ee5c # Hard reset salt myminion git.reset /path/to/repo opts='--hard origin/master' """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.append("reset") command.extend(_format_opts(opts)) return _git_run( command, cwd=cwd, user=user, password=password, identity=identity, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def rev_parse( cwd, rev=None, opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ .. versionadded:: 2015.8.0 Interface to `git-rev-parse(1)`_ cwd The path to the git checkout rev Revision to parse. See the `SPECIFYING REVISIONS`_ section of the `git-rev-parse(1)`_ manpage for details on how to format this argument. This argument is optional when using the options in the `Options for Files` section of the `git-rev-parse(1)`_ manpage. opts Any additional options to add to the command line, in a single string git_opts Any additional options to add to git command itself (not the ``rev-parse`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-rev-parse(1)`: http://git-scm.com/docs/git-rev-parse .. _`SPECIFYING REVISIONS`: http://git-scm.com/docs/git-rev-parse#_specifying_revisions .. _`Options for Files`: http://git-scm.com/docs/git-rev-parse#_options_for_files CLI Examples: .. code-block:: bash # Get the full SHA1 for HEAD salt myminion git.rev_parse /path/to/repo HEAD # Get the short SHA1 for HEAD salt myminion git.rev_parse /path/to/repo HEAD opts='--short' # Get the develop branch's upstream tracking branch salt myminion git.rev_parse /path/to/repo 'develop@{upstream}' opts='--abbrev-ref' # Get the SHA1 for the commit corresponding to tag v1.2.3 salt myminion git.rev_parse /path/to/repo 'v1.2.3^{commit}' # Find out whether or not the repo at /path/to/repo is a bare repository salt myminion git.rev_parse /path/to/repo opts='--is-bare-repository' """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.append("rev-parse") command.extend(_format_opts(opts)) if rev is not None: command.append(rev) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def revision( cwd, rev="HEAD", short=False, user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ Returns the SHA1 hash of a given identifier (hash, branch, tag, HEAD, etc.) cwd The path to the git checkout rev : HEAD The revision short : False If ``True``, return an abbreviated SHA1 git hash user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Example: .. code-block:: bash salt myminion git.revision /path/to/repo mybranch """ cwd = _expand_path(cwd, user) command = ["git", "rev-parse"] if short: command.append("--short") command.append(rev) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def rm_( cwd, filename, opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ Interface to `git-rm(1)`_ cwd The path to the git checkout filename The location of the file/directory to remove, relative to ``cwd`` .. note:: To remove a directory, ``-r`` must be part of the ``opts`` parameter. opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``rm`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-rm(1)`: http://git-scm.com/docs/git-rm CLI Examples: .. code-block:: bash salt myminion git.rm /path/to/repo foo/bar.py salt myminion git.rm /path/to/repo foo/bar.py opts='--dry-run' salt myminion git.rm /path/to/repo foo/baz opts='-r' """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.append("rm") command.extend(_format_opts(opts)) command.extend(["--", filename]) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def stash( cwd, action="save", opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ Interface to `git-stash(1)`_, returns the stdout from the git command cwd The path to the git checkout opts Any additional options to add to the command line, in a single string. Use this to complete the ``git stash`` command by adding the remaining arguments (i.e. ``'save <stash comment>'``, ``'apply stash@{2}'``, ``'show'``, etc.). Omitting this argument will simply run ``git stash``. git_opts Any additional options to add to git command itself (not the ``stash`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-stash(1)`: http://git-scm.com/docs/git-stash CLI Examples: .. code-block:: bash salt myminion git.stash /path/to/repo save opts='work in progress' salt myminion git.stash /path/to/repo apply opts='stash@{1}' salt myminion git.stash /path/to/repo drop opts='stash@{1}' salt myminion git.stash /path/to/repo list """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.extend(["stash", action]) command.extend(_format_opts(opts)) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def status(cwd, user=None, password=None, ignore_retcode=False, output_encoding=None): """ .. versionchanged:: 2015.8.0 Return data has changed from a list of lists to a dictionary Returns the changes to the repository cwd The path to the git checkout user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Example: .. code-block:: bash salt myminion git.status /path/to/repo """ cwd = _expand_path(cwd, user) state_map = {"M": "modified", "A": "new", "D": "deleted", "??": "untracked"} ret = {} command = ["git", "status", "-z", "--porcelain"] output = _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] for line in output.split("\0"): try: state, filename = line.split(None, 1) except ValueError: continue ret.setdefault(state_map.get(state, state), []).append(filename) return ret def submodule( cwd, command, opts="", git_opts="", user=None, password=None, identity=None, ignore_retcode=False, saltenv="base", output_encoding=None, **kwargs, ): """ .. versionchanged:: 2015.8.0 Added the ``command`` argument to allow for operations other than ``update`` to be run on submodules, and deprecated the ``init`` argument. To do a submodule update with ``init=True`` moving forward, use ``command=update opts='--init'`` Interface to `git-submodule(1)`_ cwd The path to the submodule command Submodule command to run, see `git-submodule(1) <git submodule>` for more information. Any additional arguments after the command (such as the URL when adding a submodule) must be passed in the ``opts`` parameter. .. versionadded:: 2015.8.0 opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``submodule`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. init : False If ``True``, ensures that new submodules are initialized .. deprecated:: 2015.8.0 Pass ``init`` as the ``command`` parameter, or include ``--init`` in the ``opts`` param with ``command`` set to update. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 identity Path to a private key to use for ssh URLs .. warning:: Unless Salt is invoked from the minion using ``salt-call``, the key(s) must be passphraseless. For greater security with passphraseless private keys, see the `sshd(8)`_ manpage for information on securing the keypair from the remote side in the ``authorized_keys`` file. .. _`sshd(8)`: http://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT .. versionchanged:: 2015.8.7 Salt will no longer attempt to use passphrase-protected keys unless invoked from the minion using ``salt-call``, to prevent blocking waiting for user input. Key can also be specified as a SaltStack file server URL, eg. salt://location/identity_file .. versionchanged:: 2016.3.0 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 saltenv The default salt environment to pull sls files from .. versionadded:: 2016.3.1 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-submodule(1)`: http://git-scm.com/docs/git-submodule CLI Example: .. code-block:: bash # Update submodule and ensure it is initialized (before 2015.8.0) salt myminion git.submodule /path/to/repo/sub/repo init=True # Update submodule and ensure it is initialized (2015.8.0 and later) salt myminion git.submodule /path/to/repo/sub/repo update opts='--init' # Rebase submodule (2015.8.0 and later) salt myminion git.submodule /path/to/repo/sub/repo update opts='--rebase' # Add submodule (2015.8.0 and later) salt myminion git.submodule /path/to/repo/sub/repo add opts='https://mydomain.tld/repo.git' # Unregister submodule (2015.8.0 and later) salt myminion git.submodule /path/to/repo/sub/repo deinit """ kwargs = salt.utils.args.clean_kwargs(**kwargs) init_ = kwargs.pop("init", False) if kwargs: salt.utils.args.invalid_kwargs(kwargs) cwd = _expand_path(cwd, user) if init_: raise SaltInvocationError( "The 'init' argument is no longer supported. Either set " "'command' to 'init', or include '--init' in the 'opts' " "argument and set 'command' to 'update'." ) cmd = ["git"] + _format_git_opts(git_opts) cmd.extend(["submodule", command]) cmd.extend(_format_opts(opts)) return _git_run( cmd, cwd=cwd, user=user, password=password, identity=identity, ignore_retcode=ignore_retcode, saltenv=saltenv, output_encoding=output_encoding, )["stdout"] def symbolic_ref( cwd, ref, value=None, opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ .. versionadded:: 2015.8.0 Interface to `git-symbolic-ref(1)`_ cwd The path to the git checkout ref Symbolic ref to read/modify value If passed, then the symbolic ref will be set to this value and an empty string will be returned. If not passed, then the ref to which ``ref`` points will be returned, unless ``--delete`` is included in ``opts`` (in which case the symbolic ref will be deleted). opts Any additional options to add to the command line, in a single string git_opts Any additional options to add to git command itself (not the ``symbolic-refs`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-symbolic-ref(1)`: http://git-scm.com/docs/git-symbolic-ref CLI Examples: .. code-block:: bash # Get ref to which HEAD is pointing salt myminion git.symbolic_ref /path/to/repo HEAD # Set/overwrite symbolic ref 'FOO' to local branch 'foo' salt myminion git.symbolic_ref /path/to/repo FOO refs/heads/foo # Delete symbolic ref 'FOO' salt myminion git.symbolic_ref /path/to/repo FOO opts='--delete' """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.append("symbolic-ref") opts = _format_opts(opts) if value is not None and any(x in opts for x in ("-d", "--delete")): raise SaltInvocationError( "Value cannot be set for symbolic ref if -d/--delete is included in opts" ) command.extend(opts) command.append(ref) if value: command.extend(value) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, )["stdout"] def tag( cwd, name, ref="HEAD", message=None, opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ .. versionadded:: 2018.3.4 Interface to `git-tag(1)`_, adds and removes tags. cwd The path to the main git checkout or a linked worktree name Name of the tag ref : HEAD Which ref to tag (defaults to local clone's HEAD) .. note:: This argument is ignored when either ``-d`` or ``--delete`` is present in the ``opts`` passed to this function. message Optional message to include with the tag. If provided, an annotated tag will be created. opts Any additional options to add to the command line, in a single string .. note:: Additionally, on the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` (as in the CLI examples below) to avoid causing errors with Salt's own argument parsing. git_opts Any additional options to add to git command itself (not the ``worktree`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. _`git-tag(1)`: http://git-scm.com/docs/git-tag CLI Example: .. code-block:: bash # Create an non-annotated tag salt myminion git.tag /path/to/repo v1.2 # Create an annotated tag salt myminion git.tag /path/to/repo v1.2 message='Version 1.2' # Delete the tag salt myminion git.tag /path/to/repo v1.2 opts='-d' """ cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.append("tag") # Don't add options for annotated tags, since we'll automatically add them # if a message was passed. This keeps us from blocking on input, as passing # these options without a separate message option would launch an editor. formatted_opts = [x for x in _format_opts(opts) if x not in ("-a", "--annotate")] # Make sure that the message was not passed in the opts if any(x == "-m" or "--message" in x for x in formatted_opts): raise SaltInvocationError( 'Tag messages must be passed in the "message" argument' ) command.extend(formatted_opts) command.append(name) if "-d" not in formatted_opts and "--delete" not in formatted_opts: command.append(ref) return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, redirect_stderr=True, output_encoding=output_encoding, )["stdout"] def version(versioninfo=False): """ .. versionadded:: 2015.8.0 Returns the version of Git installed on the minion versioninfo : False If ``True``, return the version in a versioninfo list (e.g. ``[2, 5, 0]``) CLI Example: .. code-block:: bash salt myminion git.version """ contextkey = "git.version" contextkey_info = "git.versioninfo" if contextkey not in __context__: try: version_ = _git_run(["git", "--version"])["stdout"] except CommandExecutionError as exc: log.error("Failed to obtain the git version (error follows):\n%s", exc) version_ = "unknown" try: # On macOS, the git version is displayed in a different format # git version 2.21.1 (Apple Git-122.3) # On Windows: # git version 2.21.1.windows.1 # As opposed to: # git version 2.21.1 if "(" in version_: version_ = version_.split("(")[0].strip() if ".windows" in version_: version_ = version_.split(".windows")[0].strip() __context__[contextkey] = version_.strip().split()[-1].strip() except IndexError: # Somehow git --version returned no stdout while not raising an # error. Should never happen but we should still account for this # possible edge case. log.error("Running 'git --version' returned no stdout") __context__[contextkey] = "unknown" if not versioninfo: return __context__[contextkey] if contextkey_info not in __context__: # Set ptr to the memory location of __context__[contextkey_info] to # prevent repeated dict lookups ptr = __context__.setdefault(contextkey_info, []) for part in __context__[contextkey].split("."): try: ptr.append(int(part)) except ValueError: ptr.append(part) return __context__[contextkey_info] def worktree_add( cwd, worktree_path, ref=None, reset_branch=None, force=None, detach=False, opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, **kwargs, ): """ .. versionadded:: 2015.8.0 Interface to `git-worktree(1)`_, adds a worktree cwd The path to the git checkout worktree_path Path to the new worktree. Can be either absolute, or relative to ``cwd``. branch Name of new branch to create. If omitted, will be set to the basename of the ``worktree_path``. For example, if the ``worktree_path`` is ``/foo/bar/baz``, then ``branch`` will be ``baz``. ref Name of the ref on which to base the new worktree. If omitted, then ``HEAD`` is use, and a new branch will be created, named for the basename of the ``worktree_path``. For example, if the ``worktree_path`` is ``/foo/bar/baz`` then a new branch ``baz`` will be created, and pointed at ``HEAD``. reset_branch : False If ``False``, then `git-worktree(1)`_ will fail to create the worktree if the targeted branch already exists. Set this argument to ``True`` to reset the targeted branch to point at ``ref``, and checkout the newly-reset branch into the new worktree. force : False By default, `git-worktree(1)`_ will not permit the same branch to be checked out in more than one worktree. Set this argument to ``True`` to override this. opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` to avoid causing errors with Salt's own argument parsing. All CLI options for adding worktrees as of Git 2.5.0 are already supported by this function as of Salt 2015.8.0, so using this argument is unnecessary unless new CLI arguments are added to `git-worktree(1)`_ and are not yet supported in Salt. git_opts Any additional options to add to git command itself (not the ``worktree`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-worktree(1)`: http://git-scm.com/docs/git-worktree CLI Examples: .. code-block:: bash salt myminion git.worktree_add /path/to/repo/main ../hotfix ref=origin/master salt myminion git.worktree_add /path/to/repo/main ../hotfix branch=hotfix21 ref=v2.1.9.3 """ _check_worktree_support() kwargs = salt.utils.args.clean_kwargs(**kwargs) branch_ = kwargs.pop("branch", None) if kwargs: salt.utils.args.invalid_kwargs(kwargs) cwd = _expand_path(cwd, user) if branch_ and detach: raise SaltInvocationError("Only one of 'branch' and 'detach' is allowed") command = ["git"] + _format_git_opts(git_opts) command.extend(["worktree", "add"]) if detach: if force: log.warning( "'force' argument to git.worktree_add is ignored when detach=True" ) command.append("--detach") else: if not branch_: branch_ = os.path.basename(worktree_path) command.extend(["-B" if reset_branch else "-b", branch_]) if force: command.append("--force") command.extend(_format_opts(opts)) command.append(worktree_path) if ref: command.append(ref) # Checkout message goes to stderr return _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, redirect_stderr=True, output_encoding=output_encoding, )["stdout"] def worktree_prune( cwd, dry_run=False, verbose=True, expire=None, opts="", git_opts="", user=None, password=None, ignore_retcode=False, output_encoding=None, ): """ .. versionadded:: 2015.8.0 Interface to `git-worktree(1)`_, prunes stale worktree administrative data from the gitdir cwd The path to the main git checkout or a linked worktree dry_run : False If ``True``, then this function will report what would have been pruned, but no changes will be made. verbose : True Report all changes made. Set to ``False`` to suppress this output. expire Only prune unused worktree data older than a specific period of time. The date format for this parameter is described in the documentation for the ``gc.pruneWorktreesExpire`` config param in the `git-config(1)`_ manpage. opts Any additional options to add to the command line, in a single string .. note:: On the Salt CLI, if the opts are preceded with a dash, it is necessary to precede them with ``opts=`` to avoid causing errors with Salt's own argument parsing. All CLI options for pruning worktrees as of Git 2.5.0 are already supported by this function as of Salt 2015.8.0, so using this argument is unnecessary unless new CLI arguments are added to `git-worktree(1)`_ and are not yet supported in Salt. git_opts Any additional options to add to git command itself (not the ``worktree`` subcommand), in a single string. This is useful for passing ``-c`` to run git with temporary changes to the git configuration. .. versionadded:: 2017.7.0 .. note:: This is only supported in git 1.7.2 and newer. user User under which to run the git command. By default, the command is run by the user under which the minion is running. password Windows only. Required when specifying ``user``. This parameter will be ignored on non-Windows platforms. .. versionadded:: 2016.3.4 ignore_retcode : False If ``True``, do not log an error to the minion log if the git command returns a nonzero exit status. .. versionadded:: 2015.8.0 output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 .. _`git-worktree(1)`: http://git-scm.com/docs/git-worktree .. _`git-config(1)`: http://git-scm.com/docs/git-config/2.5.1 CLI Examples: .. code-block:: bash salt myminion git.worktree_prune /path/to/repo salt myminion git.worktree_prune /path/to/repo dry_run=True salt myminion git.worktree_prune /path/to/repo expire=1.day.ago """ _check_worktree_support() cwd = _expand_path(cwd, user) command = ["git"] + _format_git_opts(git_opts) command.extend(["worktree", "prune"]) if dry_run: command.append("--dry-run") if verbose: command.append("--verbose") if expire: command.extend(["--expire", expire]) command.extend(_format_opts(opts)) result = _git_run( command, cwd=cwd, user=user, password=password, ignore_retcode=ignore_retcode, output_encoding=output_encoding, ) git_version = version(versioninfo=False) if LooseVersion(git_version) > LooseVersion("2.35.0"): return result["stderr"] return result["stdout"] def worktree_rm(cwd, user=None, output_encoding=None): """ .. versionadded:: 2015.8.0 Recursively removes the worktree located at ``cwd``, returning ``True`` if successful. This function will attempt to determine if ``cwd`` is actually a worktree by invoking :py:func:`git.is_worktree <salt.modules.git.is_worktree>`. If the path does not correspond to a worktree, then an error will be raised and no action will be taken. .. warning:: There is no undoing this action. Be **VERY** careful before running this function. cwd Path to the worktree to be removed user Used for path expansion when ``cwd`` is not an absolute path. By default, when ``cwd`` is not absolute, the path will be assumed to be relative to the home directory of the user under which the minion is running. Setting this option will change the home directory from which path expansion is performed. output_encoding Use this option to specify which encoding to use to decode the output from any git commands which are run. This should not be needed in most cases. .. note:: This should only be needed if the files in the repository were created with filenames using an encoding other than UTF-8 to handle Unicode characters. .. versionadded:: 2018.3.1 CLI Examples: .. code-block:: bash salt myminion git.worktree_rm /path/to/worktree """ _check_worktree_support() cwd = _expand_path(cwd, user) if not os.path.exists(cwd): raise CommandExecutionError(cwd + " does not exist") elif not is_worktree(cwd, output_encoding=output_encoding): raise CommandExecutionError(cwd + " is not a git worktree") try: salt.utils.files.rm_rf(cwd) except Exception as exc: # pylint: disable=broad-except raise CommandExecutionError(f"Unable to remove {cwd}: {exc}") return True