Class: RubyGit::Worktree

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_git/worktree.rb

Overview

The working tree is a directory tree consisting of the checked out files that you are currently working on.

Create a new Worktree using Worktree.init, Worktree.clone, or Worktree.open.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#pathPathname (readonly)

The root path of the working tree

Examples:

worktree_path = '/Users/James/myproject'
worktree = Worktree.open(worktree_path)
worktree.path
 => '/Users/James/myproject'

Returns:

  • (Pathname)

    the root path of the worktree



20
21
22
# File 'lib/ruby_git/worktree.rb', line 20

def path
  @path
end

Class Method Details

.clone(repository_url, to_path: nil) ⇒ RubyGit::Worktree

Copy the remote repository and checkout the default branch

Clones the repository referred to by repository_url into a newly created directory, creates remote-tracking branches for each branch in the cloned repository, and checks out the default branch in the Git working tree whose root directory is to_path.

to_path will be created if it does not exist. An error is raised if to_path exists and not an empty directory.

Examples:

Using default for Worktree path

FileUtils.pwd
 => "/Users/jsmith"
worktree = Worktree.clone('https://github.com/main-branch/ruby_git.git')
worktree.path
 => "/Users/jsmith/ruby_git"

Using a specified worktree_path

FileUtils.pwd
 => "/Users/jsmith"
worktree_path = '/tmp/project'
worktree = Worktree.clone('https://github.com/main-branch/ruby_git.git', to_path: worktree_path)
worktree.path
 => "/tmp/project"

Parameters:

  • repository_url (String)

    a reference to a Git repository

  • to_path (String) (defaults to: nil)

    where to put the checked out Git working tree once the repository is cloned

Returns:

  • (RubyGit::Worktree)

    the Git working tree checked out from the cloned repository

Raises:

  • (RubyGit::FailedError)

    if (1) repository_url is not valid or does not point to a valid repository OR (2) to_path is not an empty directory.

See Also:



100
101
102
103
104
105
106
# File 'lib/ruby_git/worktree.rb', line 100

def self.clone(repository_url, to_path: nil)
  command = ['clone', '--', repository_url]
  command << to_path if to_path
  options = { out: StringIO.new, err: StringIO.new }
  clone_output = RubyGit::CommandLine.run(*command, **options).stderr
  new(cloned_to(clone_output))
end

.cloned_to(clone_output) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get path of the cloned worktree from git clone stderr output

Parameters:

  • clone_output (String)

    the stderr output of the git clone command

Returns:

  • (String)

    the path of the cloned worktree



115
116
117
# File 'lib/ruby_git/worktree.rb', line 115

def self.cloned_to(clone_output)
  clone_output.match(/Cloning into ['"](.+)['"]\.\.\./)[1]
end

.init(worktree_path) ⇒ RubyGit::Worktree

Create an empty Git repository under the root working tree path

If the repository already exists, it will not be overwritten.

Examples:

worktree = Worktree.init(worktree_path)

Parameters:

  • worktree_path (String)

    the root path of a Git working tree

Returns:

Raises:

See Also:



37
38
39
40
41
42
43
44
45
# File 'lib/ruby_git/worktree.rb', line 37

def self.init(worktree_path)
  raise RubyGit::Error, "Path '#{worktree_path}' not valid." unless File.directory?(worktree_path)

  command = ['init']
  options = { chdir: worktree_path, out: StringIO.new, err: StringIO.new }
  RubyGit::CommandLine.run(*command, **options)

  new(worktree_path)
end

.open(worktree_path) ⇒ RubyGit::Worktree

Open an existing Git working tree that contains worktree_path

Examples:

worktree = Worktree.open(worktree_path)

Parameters:

  • worktree_path (String)

    the root path of a Git working tree

Returns:

Raises:

  • (RubyGit::Error)

    if worktree_path does not exist, is not a directory, or is not within a Git working tree.

See Also:



61
62
63
# File 'lib/ruby_git/worktree.rb', line 61

def self.open(worktree_path)
  new(worktree_path)
end

Instance Method Details

#add(*pathspecs, all: false, force: false, refresh: false, update: false) ⇒ RubyGit::CommandLineResult

Add changed files to the index to stage for the next commit

Examples:

worktree = Worktree.open(worktree_path)
worktree.add('file1.txt', 'file2.txt')
worktree.add('.')
worktree.add(all: true)

Parameters:

  • pathspecs (Array<String>)

    paths to add to the index

  • all (Boolean) (defaults to: false)

    adds, updates, and removes index entries to match the working tree (entire repo)

  • force (Boolean) (defaults to: false)

    add files even if they are ignored

  • refresh (Boolean) (defaults to: false)

    only refresh each files stat information in the index

  • update (Boolean) (defaults to: false)

    add all updated and deleted files to the index but does not add any files

Returns:

  • (RubyGit::CommandLineResult)

    the result of the git add command

Raises:

  • (ArgumentError)

    if any of the options are not valid

See Also:



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/ruby_git/worktree.rb', line 181

def add(*pathspecs, all: false, force: false, refresh: false, update: false) # rubocop:disable Metrics/MethodLength
  validate_boolean_option(name: :all, value: all)
  validate_boolean_option(name: :force, value: force)
  validate_boolean_option(name: :refresh, value: refresh)
  validate_boolean_option(name: :update, value: update)

  command = %w[add]
  command << '--all' if all
  command << '--force' if force
  command << '--update' if update
  command << '--refresh' if refresh
  command << '--' unless pathspecs.empty?
  command.concat(pathspecs)

  options = { out: StringIO.new, err: StringIO.new }

  run(*command, **options)
end

#repositoryRubyGit::Repository

Return the repository associated with the worktree

Examples:

worktree = Worktree.open(worktree_path)
worktree.repository #=> #<RubyGit::Repository ...>

Returns:



208
209
210
211
212
213
214
215
216
# File 'lib/ruby_git/worktree.rb', line 208

def repository
  @repository ||= begin
    command = %w[rev-parse --git-dir]
    options = { chdir: path, chomp: true, out: StringIO.new, err: StringIO.new }
    # rev-parse path might be relative to the worktree, thus the need to expand it
    git_dir = File.realpath(RubyGit::CommandLine.run(*command, **options).stdout, path)
    Repository.new(git_dir)
  end
end

#status(*path_specs, untracked_files: :all, ignored: :no, ignore_submodules: :all) ⇒ RubyGit::Status::Report

Show the working tree and index status

handled

See git-staus --untracked-files.

handled, :no to not include ignored files

See git-staus --ignored.

Examples:

worktree = Worktree.open(worktree_path) worktree.status #=>

#<RubyGit::Status::Report ...>

Parameters:

  • path_specs (Array<String>)

    paths to limit the status to (default is all paths)

    See git-glossary pathspec.

  • untracked_files (:all, :normal, :no) (defaults to: :all)

    Defines how untracked files will be

  • ignored (:traditional, :matching, :no) (defaults to: :no)

    Defines how ignored files will be

  • ignore_submodules (:all, :dirty, :untracked, :none) (defaults to: :all)

    Default is :all

    See git-staus --ignore-submodules.

Returns:



149
150
151
152
153
154
155
156
157
158
159
# File 'lib/ruby_git/worktree.rb', line 149

def status(*path_specs, untracked_files: :all, ignored: :no, ignore_submodules: :all)
  command = %w[status --porcelain=v2 --branch --show-stash --ahead-behind --renames -z]
  command << "--untracked-files=#{untracked_files}"
  command << "--ignored=#{ignored}"
  command << "--ignore-submodules=#{ignore_submodules}"
  command << '--' unless path_specs.empty?
  command.concat(path_specs)
  options = { out: StringIO.new, err: StringIO.new }
  status_output = run(*command, **options).stdout
  RubyGit::Status.parse(status_output)
end