Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Git::Lib#stash_save not compatible with git 2.30.2 #537

Open
costa opened this issue Sep 12, 2021 · 1 comment
Open

Git::Lib#stash_save not compatible with git 2.30.2 #537

costa opened this issue Sep 12, 2021 · 1 comment

Comments

@costa
Copy link

costa commented Sep 12, 2021

Subject of the issue

Git::Lib#stash_save seems to prepend '-- ' to stash message with specific git version

Your environment

  • version of git 2.30.2 and ruby-git 1.9.1
  • version of ruby 2.6.8p205

Steps to reproduce

gitx = Git::Lib.new(Git.init('.'))
gitx.stash_save 'SOME-MSG'`
gitx.stashes_all

Expected behaviour

=> [0, 'SOME-MSG']

Actual behaviour

=> [0, '-- SOME-MSG']

@stale stale bot added the stale label Jan 9, 2022
@jcouball jcouball removed the stale label Mar 3, 2023
@ruby-git ruby-git deleted a comment from stale bot Mar 4, 2023
@jcouball
Copy link
Member

jcouball commented Mar 5, 2023

The implementation of stashes in this gem are broken and need a complete rewrite. The design doesn't seem right either. For instance, I don't understand why stashes are only accessed via a Branch object (unless you go via Git::Lib which I view as an implementation detail).

I can't imagine that anyone is using the current implementation.

Here is my sketch of how I'd like to implement it.

module Git
  Stash = Struct.new(
    :ref, :sha, :committed_on, :committer_email, :committer_name, :message,
    keyword_init: true
  )

  class Stash
    # Any method that accepts a stash reference as a string can also accept a
    # Stash object
    def to_s
      ref
    end
  end
end

require 'forwardable'

module Git
  class Base
    extend Forwardable

    # Stash methods that are delegated to @lib:
    #
    def_delegators :@lib, :stash_list, :stash_push, :stash_pop, :stash_apply, :stash_branch, :stash_clear, :stash_drop
  end

  class Lib
    # List the current stash entries
    #
    # @return [Array<Git::Stash>]
    #
    def stash_list
      o = `git stash list "--format=format:%gD%x00%H%x00%cI%x00%ce%x00%cn%x00%s"`
      fields = [:ref, :sha, :committed_on, :committer_email, :committer_name, :message]
      o.split("\n").map { |line| Stash.new(**Hash[fields.zip(line.split("\u0000"))]) }
    end

    # Save local modifications to a new stash entry and roll them back to HEAD
    #
    # @param message [String, nil]
    # @param pathspec [String, Array<String>, nil]
    # @param keep_index [Boolean] changes already added to the index are left intact
    # @param include_untracked [Boolean] also save untracked files
    # @param all [Boolean] also save untrackeed and ignored files
    #
    # @return [Git::Stash] the stash that was created
    #
    # @raises [Git::FailedError] if the stash could not be pushed
    #
    def stash_push(message: nil, pathspec: nil, keep_index: false, include_untracked: false, all: false)
    end

    # Remove a single stashed state from the stash list and apply it on top of the current working tree
    #
    # @param stash [#to_s, nil] the stash to apply must be a reference of the form `stash@{<revision>}`
    # @param index [Boolean] reinstates not only the working tree’s changes, but also the index’s ones too
    #
    # @return [Git::Stash] the stash that was applied
    #
    # @raises [Git::FailedError] if the stash could not be applied
    #
    def stash_pop(stash: nil, index: false)
    end

    # Like pop, but does not remove the state from the stash list
    #
    def stash_apply(stash: nil, index: false)
    end

    # Checks out a stash to a new branch
    #
    # The branch starts from the commit at which the <stash> was originally created,
    # applies the changes recorded in <stash> to the new working tree and index. If
    # that succeeds, and <stash> is a reference of the form stash@{<revision>}, it
    # then drops the <stash>. When no <stash> is given, applies the latest one.
    #
    # @param branch [String] the name of the branch to create
    # @param stash [#to_s, nil] the stash to apply must be a reference of the form `stash@{<revision>}`
    #
    # @return [Branch] the branch that was created
    #
    # @raise [Git::FailedError] if the branch could not be created or the stash could not be applied
    #
    def stash_branch(branch:, stash: nil)
    end

    # Remove all stash entries
    #
    # @return [Array<Git::Stash>] the stashes that were dropped (their ref's will be nil)
    #
    def stash_clear
    end

    # Remove a single stashed state from the stash list
    #
    # @param stash [#to_s, nil] the stash to drop must be a reference of the form `stash@{<revision>}`
    #
    # @return [Git::Stash] the stash that was dropped (its ref will be nil)
    #
    # @raises [Git::FailedError] if the stash could not be dropped
    #
    def stash_drop(stash: nil)
    end
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants