From 12f908c2122ac539cef04474947535a5786bd15e Mon Sep 17 00:00:00 2001 From: James Couball Date: Mon, 28 Dec 2020 13:45:04 -0800 Subject: [PATCH] Add YARD documentation to ruby-git (#502) Signed-off-by: James Couball --- .gitignore | 2 + .yardopts | 11 +++ CHANGELOG.md | 5 + CONTRIBUTING.md | 7 +- MAINTAINERS.md | 5 + README.md | 29 +++++- RELEASING.md | 5 + Rakefile | 38 ++++++- git.gemspec | 27 +++-- lib/git.rb | 212 ++++++++++++++++++++++++++++++++-------- lib/git/base.rb | 207 ++++++++++++++++++++++----------------- lib/git/base/factory.rb | 47 +++++---- lib/git/lib.rb | 42 +++++++- 13 files changed, 471 insertions(+), 166 deletions(-) create mode 100644 .yardopts diff --git a/.gitignore b/.gitignore index 8394ee1d..611ed70c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ *.sw? .DS_Store coverage +doc +.yardoc pkg rdoc Gemfile.lock diff --git a/.yardopts b/.yardopts new file mode 100644 index 00000000..ce1aff3c --- /dev/null +++ b/.yardopts @@ -0,0 +1,11 @@ +--default-return='' +--hide-void-return +--markup-provider=redcarpet +--markup=markdown +--fail-on-warning +- +README.md +CHANGELOG.md +CONTRIBUTING.md +RELEASING.md +MAINTAINERS.md diff --git a/CHANGELOG.md b/CHANGELOG.md index bb00ccdf..554bd62c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + + # Change Log ## 1.7.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c81ffb26..929b80b2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,8 @@ + + # Contributing to ruby-git Thank you for your interest in contributing to the ruby-git project. @@ -8,7 +13,7 @@ judgement. Propose changes to these guidelines with a pull request. -## How to contribute to ruby-git +## How to contribute You can contribute in two ways: diff --git a/MAINTAINERS.md b/MAINTAINERS.md index a78a67d6..2d8ac7b1 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -1,3 +1,8 @@ + + # Maintainers When making changes in this repository, one of the maintainers below must review and approve your pull request. diff --git a/README.md b/README.md index f90a7be4..0ff9a0a5 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,36 @@ -# Git Library for Ruby + -Library for using Git in Ruby. +# The Git Gem + +The Git Gem provides an API that can be used to create, read, and manipulate +Git repositories by wrapping system calls to the `git` binary. The API can be +used for working with Git in complex interactions including branching and +merging, object inspection and manipulation, history, patch generation and +more. ## Homepage -Git public hosting of the project source code is at: +The project source code is at: http://github.com/ruby-git/ruby-git +## Documentation + +Detailed documentation can be found at: + +https://rubydoc.info/gems/git/Git.html + +Get started by obtaining a repository object by: + +* opening an existing working copy with [Git.open](https://rubydoc.info/gems/git/Git#open-class_method) +* initializing a new repository with [Git.init](https://rubydoc.info/gems/git/Git#init-class_method) +* cloning a repository with [Git.clone](https://rubydoc.info/gems/git/Git#clone-class_method) + +Methods that can be called on a repository object are documented in [Git::Base](https://rubydoc.info/gems/git/Git/Base) + ## Install You can install Ruby/Git like this: diff --git a/RELEASING.md b/RELEASING.md index af99786f..7f360370 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,3 +1,8 @@ + + # How to release a new git.gem Releasing a new version of the `git` gem requires these steps: diff --git a/Rakefile b/Rakefile index 0dc79a58..cda2f8cf 100644 --- a/Rakefile +++ b/Rakefile @@ -1,16 +1,44 @@ require 'bundler/gem_tasks' -require 'rubygems' require "#{File.expand_path(File.dirname(__FILE__))}/lib/git/version" -task :default => :test +default_tasks = [] desc 'Run Unit Tests' -task :test do |t| +task :test do sh 'git config --global user.email "git@example.com"' if `git config user.email`.empty? sh 'git config --global user.name "GitExample"' if `git config user.name`.empty? - $VERBOSE = true - require File.dirname(__FILE__) + '/tests/all_tests.rb' end +default_tasks << :test + +unless RUBY_PLATFORM == 'java' + # + # YARD documentation for this project can NOT be built with JRuby. + # This project uses the redcarpet gem which can not be installed on JRuby. + # + require 'yard' + YARD::Rake::YardocTask.new + CLEAN << '.yardoc' + CLEAN << 'doc' + default_tasks << :yard + + require 'yardstick/rake/verify' + Yardstick::Rake::Verify.new(:'yardstick:coverage') do |t| + t.threshold = 50 + t.require_exact_threshold = false + end + default_tasks << :'yardstick:coverage' + + desc 'Run yardstick to check yard docs' + task :yardstick do + sh "yardstick 'lib/**/*.rb'" + end + # Do not include yardstick as a default task for now since there are too many + # warnings. Will work to get the warnings down before re-enabling it. + # + # default_tasks << :yardstick +end + +task default: default_tasks diff --git a/git.gemspec b/git.gemspec index 27ca1476..2f14c991 100644 --- a/git.gemspec +++ b/git.gemspec @@ -7,9 +7,20 @@ Gem::Specification.new do |s| s.homepage = 'http://github.com/ruby-git/ruby-git' s.license = 'MIT' s.name = 'git' - s.summary = 'Ruby/Git is a Ruby library that can be used to create, read and manipulate Git repositories by wrapping system calls to the git binary.' + s.summary = 'An API to create, read, and manipulate Git repositories' + s.description = <<~DESCRIPTION + The Git Gem provides an API that can be used to create, read, and manipulate + Git repositories by wrapping system calls to the `git` binary. The API can be + used for working with Git in complex interactions including branching and + merging, object inspection and manipulation, history, patch generation and + more. + DESCRIPTION s.version = Git::VERSION + s.metadata['homepage_uri'] = s.homepage + s.metadata['source_code_uri'] = s.homepage + s.metadata['changelog_uri'] = 'http://rubydoc.info/gems/git/file.CHANGELOG.html' + s.require_paths = ['lib'] s.required_ruby_version = '>= 2.3' s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to?(:required_rubygems_version=) @@ -17,13 +28,15 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'rchardet', '~> 1.8' - s.add_development_dependency 'rake' - s.add_development_dependency 'rdoc' - s.add_development_dependency 'minitar', '0.9' - s.add_development_dependency 'test-unit', '>=2', '< 4' + s.add_development_dependency 'minitar', '~> 0.9' + s.add_development_dependency 'rake', '~> 13.0' + s.add_development_dependency 'test-unit', '~> 3.3' - s.extra_rdoc_files = ['README.md'] - s.rdoc_options = ['--charset=UTF-8'] + unless RUBY_PLATFORM == 'java' + s.add_development_dependency 'redcarpet', '~> 3.5' + s.add_development_dependency 'yard', '~> 0.9' + s.add_development_dependency 'yardstick', '~> 0.9' + end s.files = [ 'CHANGELOG.md', diff --git a/lib/git.rb b/lib/git.rb index 6e4a7e5d..eb4c7cce 100644 --- a/lib/git.rb +++ b/lib/git.rb @@ -29,23 +29,14 @@ $stderr.puts "[WARNING] The git gem requires git #{lib.required_command_version.join('.')} or later, but only found #{lib.current_command_version.join('.')}. You should probably upgrade." end -# Git/Ruby Library -# -# This provides bindings for working with git in complex -# interactions, including branching and merging, object -# inspection and manipulation, history, patch generation -# and more. You should be able to do most fundamental git -# operations with this library. -# -# This module provides the basic functions to open a git +# The Git module provides the basic functions to open a git # reference to work with. You can open a working directory, # open a bare repository, initialize a new repo or clone an # existing remote repository. # -# Author:: Scott Chacon (mailto:schacon@gmail.com) -# License:: MIT License +# @author Scott Chacon (mailto:schacon@gmail.com) +# module Git - #g.config('user.name', 'Scott Chacon') # sets value #g.config('user.email', 'email@email.com') # sets value #g.config('user.name') # returns 'Scott Chacon' @@ -76,25 +67,93 @@ def global_config(name = nil, value = nil) self.class.global_config(name, value) end - # open a bare repository + # Open a bare repository + # + # Opens a bare repository located in the `git_dir` directory. + # Since there is no working copy, you can not checkout or commit + # but you can do most read operations. + # + # @see https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbarerepositoryabarerepository + # What is a bare repository? + # + # @example Open a bare repository and retrieve the first commit SHA + # repository = Git.bare('ruby-git.git') + # puts repository.log[0].sha #=> "64c6fa011d3287bab9158049c85f3e85718854a0" + # + # @param [Pathname] git_dir The path to the bare repository directory + # containing an initialized Git repository. If a relative path is given, it + # is converted to an absolute path using + # [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path). + # + # @param [Hash] options The options for this command (see list of valid + # options below) + # + # @option options [Logger] :log A logger to use for Git operations. Git commands + # are logged at the `:info` level. Additional logging is done at the `:debug` + # level. + # + # @return [Git::Base] an object that can execute git commands in the context + # of the bare repository. # - # this takes the path to a bare git repo - # it expects not to be able to use a working directory - # so you can't checkout stuff, commit things, etc. - # but you can do most read operations def self.bare(git_dir, options = {}) Base.bare(git_dir, options) end - # clones a remote repository + # Clone a repository into an empty or newly created directory # - # options - # :bare => true (does a bare clone) - # :repository => '/path/to/alt_git_dir' - # :index => '/path/to/alt_index_file' + # @see https://git-scm.com/docs/git-clone git clone + # @see https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a GIT URLs + # + # @param [URI, Pathname] repository The (possibly remote) repository to clone + # from. See [GIT URLS](https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a) + # for more information. + # + # @param [Pathname] name The directory to clone into. # - # example - # Git.clone('git://repo.or.cz/rubygit.git', 'clone.git', :bare => true) + # @param [Hash] options The options for this command (see list of valid + # options below) + # + # @option options [Boolean] :bare Make a bare Git repository. See + # [what is a bare repository?](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbarerepositoryabarerepository). + # + # @option options [String] :branch The name of a branch or tag to checkout + # instead of the default branch. + # + # @option options [Integer] :depth Create a shallow clone with a history + # truncated to the specified number of commits. + # + # @option options [Logger] :log A logger to use for Git operations. Git + # commands are logged at the `:info` level. Additional logging is done + # at the `:debug` level. + # + # @option options [Boolean] :mirror Set up a mirror of the source repository. + # + # @option options [String] :origin Use the value instead `origin` to track + # the upstream repository. + # + # @option options [Pathname] :path The directory to clone into. May be used + # as an alternative to the `directory` parameter. If specified, the + # `path` option is used instead of the `directory` parameter. + # + # @option options [Boolean] :recursive After the clone is created, initialize + # all submodules within, using their default settings. + # + # @example Clone into the default directory `ruby-git` + # git = Git.clone('https://github.com/ruby-git/ruby-git.git') + # + # @example Clone and then checkout the `development` branch + # git = Git.clone('https://github.com/ruby-git/ruby-git.git', branch: 'development') + # + # @example Clone into a different directory `my-ruby-git` + # git = Git.clone('https://github.com/ruby-git/ruby-git.git', 'my-ruby-git') + # # or: + # git = Git.clone('https://github.com/ruby-git/ruby-git.git', path: 'my-ruby-git') + # + # @example Create a bare repository in the directory `ruby-git.git` + # git = Git.clone('https://github.com/ruby-git/ruby-git.git', bare: true) + # + # @return [Git::Base] an object that can execute git commands in the context + # of the cloned local working copy or cloned repository. # def self.clone(repository, name, options = {}) Base.clone(repository, name, options) @@ -134,13 +193,55 @@ def self.global_config(name = nil, value = nil) end end - # initialize a new git repository, defaults to the current working directory + # Create an empty Git repository or reinitialize an existing Git repository # - # options - # :repository => '/path/to/alt_git_dir' - # :index => '/path/to/alt_index_file' - def self.init(working_dir = '.', options = {}) - Base.init(working_dir, options) + # @param [Pathname] directory If the `:bare` option is NOT given or is not + # `true`, the repository will be created in `"#{directory}/.git"`. + # Otherwise, the repository is created in `"#{directory}"`. + # + # All directories along the path to `directory` are created if they do not exist. + # + # A relative path is referenced from the current working directory of the process + # and converted to an absolute path using + # [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path). + # + # @param [Hash] options The options for this command (see list of valid + # options below) + # + # @option options [Boolean] :bare Instead of creating a repository at + # `"#{directory}/.git"`, create a bare repository at `"#{directory}"`. + # See [what is a bare repository?](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbarerepositoryabarerepository). + # + # @option options [Pathname] :repository the path to put the newly initialized + # Git repository. The default for non-bare repository is `"#{directory}/.git"`. + # + # A relative path is referenced from the current working directory of the process + # and converted to an absolute path using + # [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path). + # + # @option options [Logger] :log A logger to use for Git operations. Git + # commands are logged at the `:info` level. Additional logging is done + # at the `:debug` level. + # + # @return [Git::Base] an object that can execute git commands in the context + # of the newly initialized repository + # + # @example Initialize a repository in the current directory + # git = Git.init + # + # @example Initialize a repository in some other directory + # git = Git.init '~/code/ruby-git' + # + # @example Initialize a bare repository + # git = Git.init '~/code/ruby-git.git', bare: true + # + # @example Initialize a repository in a non-default location (outside of the working copy) + # git = Git.init '~/code/ruby-git', repository: '~/code/ruby-git.git' + # + # @see https://git-scm.com/docs/git-init git init + # + def self.init(directory = '.', options = {}) + Base.init(directory, options) end # returns a Hash containing information about the references @@ -155,18 +256,51 @@ def self.ls_remote(location = nil, options = {}) Git::Lib.new.ls_remote(location, options) end - # open an existing git working directory + # Open a an existing Git working directory # - # this will most likely be the most common way to create - # a git reference, referring to a working directory. - # if not provided in the options, the library will assume - # your git_dir and index are in the default place (.git/, .git/index) + # Git.open will most likely be the most common way to create + # a git reference, referring to an existing working directory. + # + # If not provided in the options, the library will assume + # the repository and index are in the default places (`.git/`, `.git/index`). + # + # @example Open the Git working directory in the current directory + # git = Git.open + # + # @example Open a Git working directory in some other directory + # git = Git.open('~/Projects/ruby-git') + # + # @example Use a logger to see what is going on + # logger = Logger.new(STDOUT) + # git = Git.open('~/Projects/ruby-git', log: logger) + # + # @example Open a working copy whose repository is in a non-standard directory + # git = Git.open('~/Projects/ruby-git', repository: '~/Project/ruby-git.git') + # + # @param [Pathname] working_dir the path to the working directory to use + # for git commands. + # + # A relative path is referenced from the current working directory of the process + # and converted to an absolute path using + # [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path). + # + # @param [Hash] options The options for this command (see list of valid + # options below) + # + # @option options [Pathname] :repository used to specify a non-standard path to + # the repository directory. The default is `"#{working_dir}/.git"`. + # + # @option options [Pathname] :index used to specify a non-standard path to an + # index file. The default is `"#{working_dir}/.git/index"` + # + # @option options [Logger] :log A logger to use for Git operations. Git + # commands are logged at the `:info` level. Additional logging is done + # at the `:debug` level. + # + # @return [Git::Base] an object that can execute git commands in the context + # of the opened working copy # - # options - # :repository => '/path/to/alt_git_dir' - # :index => '/path/to/alt_index_file' def self.open(working_dir, options = {}) Base.open(working_dir, options) end - end diff --git a/lib/git/base.rb b/lib/git/base.rb index e4c21b83..fbca5f1b 100644 --- a/lib/git/base.rb +++ b/lib/git/base.rb @@ -1,31 +1,23 @@ require 'git/base/factory' module Git - + # Git::Base is the main public interface for interacting with Git commands. + # + # Instead of creating a Git::Base directly, obtain a Git::Base instance by + # calling one of the follow {Git} class methods: {Git.open}, {Git.init}, + # {Git.clone}, or {Git.bare}. + # class Base - include Git::Base::Factory - # opens a bare Git Repository - no working directory options - def self.bare(git_dir, opts = {}) - self.new({:repository => git_dir}.merge(opts)) + # (see Git.bare) + def self.bare(git_dir, options = {}) + self.new({:repository => git_dir}.merge(options)) end - # clones a git repository locally - # - # repository - http://repo.or.cz/w/sinatra.git - # name - sinatra - # - # options: - # :repository - # - # :bare - # or - # :working_directory - # :index_file - # - def self.clone(repository, name, opts = {}) - self.new(Git::Lib.new(nil, opts[:log]).clone(repository, name, opts)) + # (see Git.clone) + def self.clone(repository, name, options = {}) + self.new(Git::Lib.new(nil, options[:log]).clone(repository, name, options)) end # Returns (and initialize if needed) a Git::Config instance @@ -35,56 +27,82 @@ def self.config return @@config ||= Config.new end - # initializes a git repository - # - # options: - # :bare - # :index - # :repository - # - def self.init(working_dir, opts = {}) - opts[:working_directory] ||= working_dir - opts[:repository] ||= File.join(opts[:working_directory], '.git') + # (see Git.init) + def self.init(directory, options = {}) + options[:working_directory] ||= directory + options[:repository] ||= File.join(options[:working_directory], '.git') - FileUtils.mkdir_p(opts[:working_directory]) if opts[:working_directory] && !File.directory?(opts[:working_directory]) + FileUtils.mkdir_p(options[:working_directory]) if options[:working_directory] && !File.directory?(options[:working_directory]) - init_opts = { - :bare => opts[:bare] - } + init_options = { :bare => options[:bare] } - opts.delete(:working_directory) if opts[:bare] + options.delete(:working_directory) if options[:bare] # Submodules have a .git *file* not a .git folder. # This file's contents point to the location of # where the git refs are held (In the parent repo) - if opts[:working_directory] && File.file?(File.join(opts[:working_directory], '.git')) + if options[:working_directory] && File.file?(File.join(options[:working_directory], '.git')) git_file = File.open('.git').read[8..-1].strip - opts[:repository] = git_file - opts[:index] = git_file + '/index' + options[:repository] = git_file + options[:index] = git_file + '/index' end - Git::Lib.new(opts).init(init_opts) + # TODO: this dance seems awkward: this creates a Git::Lib so we can call + # init so we can create a new Git::Base which in turn (ultimately) + # creates another/different Git::Lib. + # + # TODO: maybe refactor so this Git::Bare.init does this: + # self.new(opts).init(init_opts) and move all/some of this code into + # Git::Bare#init. This way the init method can be called on any + # repository you have a Git::Base instance for. This would not + # change the existing interface (other than adding to it). + # + Git::Lib.new(options).init(init_options) - self.new(opts) + self.new(options) end - # opens a new Git Project from a working directory - # you can specify non-standard git_dir and index file in the options - def self.open(working_dir, opts={}) - opts[:working_directory] ||= working_dir - opts[:repository] ||= File.join(opts[:working_directory], '.git') + # (see Git.open) + def self.open(working_dir, options={}) + # TODO: move this to Git.open? + + options[:working_directory] ||= working_dir + options[:repository] ||= File.join(options[:working_directory], '.git') # Submodules have a .git *file* not a .git folder. # This file's contents point to the location of # where the git refs are held (In the parent repo) - if opts[:working_directory] && File.file?(File.join(opts[:working_directory], '.git')) + if options[:working_directory] && File.file?(File.join(options[:working_directory], '.git')) git_file = File.open('.git').read[8..-1].strip - opts[:repository] = git_file - opts[:index] = git_file + '/index' + options[:repository] = git_file + options[:index] = git_file + '/index' end - self.new(opts) + + self.new(options) end + # Create an object that executes Git commands in the context of a working + # copy or a bare repository. + # + # @param [Hash] options The options for this command (see list of valid + # options below) + # + # @option options [Pathname] :working_dir the path to the root of the working + # directory. Should be `nil` if executing commands on a bare repository. + # + # @option options [Pathname] :repository used to specify a non-standard path to + # the repository directory. The default is `"#{working_dir}/.git"`. + # + # @option options [Pathname] :index used to specify a non-standard path to an + # index file. The default is `"#{working_dir}/.git/index"` + # + # @option options [Logger] :log A logger to use for Git operations. Git + # commands are logged at the `:info` level. Additional logging is done + # at the `:debug` level. + # + # @return [Git::Base] an object that can execute git commands in the context + # of the opened working copy or bare repository + # def initialize(options = {}) if working_dir = options[:working_directory] options[:repository] ||= File.join(working_dir, '.git') @@ -198,46 +216,53 @@ def lib @lib ||= Git::Lib.new(self, @logger) end - # will run a grep for 'string' on the HEAD of the git repository - # - # to be more surgical in your grep, you can call grep() off a specific - # git object. for example: - # - # @git.object("v2.3").grep('TODO') + # Run a grep for 'string' on the HEAD of the git repository # - # in any case, it returns a hash of arrays of the type: - # hsh[tree-ish] = [[line_no, match], [line_no, match2]] - # hsh[tree-ish] = [[line_no, match], [line_no, match2]] + # @example Limit grep's scope by calling grep() from a specific object: + # git.object("v2.3").grep('TODO') # - # so you might use it like this: - # - # @git.grep("TODO").each do |sha, arr| + # @example Using grep results: + # git.grep("TODO").each do |sha, arr| # puts "in blob #{sha}:" - # arr.each do |match| - # puts "\t line #{match[0]}: '#{match[1]}'" + # arr.each do |line_no, match_string| + # puts "\t line #{line_no}: '#{match_string}'" # end # end + # + # @return [Hash] a hash of arrays + # ```Ruby + # { + # 'tree-ish1' => [[line_no1, match_string1], ...], + # 'tree-ish2' => [[line_no1, match_string1], ...], + # ... + # } + # ``` + # def grep(string, path_limiter = nil, opts = {}) self.object('HEAD').grep(string, path_limiter, opts) end # updates the repository index using the working directory content # - # @git.add('path/to/file') - # @git.add(['path/to/file1','path/to/file2']) - # @git.add(:all => true) + # @example + # git.add + # git.add('path/to/file') + # git.add(['path/to/file1','path/to/file2']) + # git.add(:all => true) # # options: # :all => true # # @param [String,Array] paths files paths to be added (optional, default='.') # @param [Hash] options - def add(*args) - if args[0].instance_of?(String) || args[0].instance_of?(Array) - self.lib.add(args[0],args[1]||{}) - else - self.lib.add('.', args[0]||{}) - end + # @option options [boolean] :all + # Update the index not only where the working tree has a file matching + # but also where the index already has an entry. + # See [the --all option to git-add](https://git-scm.com/docs/git-add#Documentation/git-add.txt--A) + # for more details. + # + def add(paths = '.', **options) + self.lib.add(paths, options) end # removes file(s) from the git repository @@ -410,20 +435,25 @@ def tags end # Creates a new git tag (Git::Tag) - # Usage: - # repo.add_tag('tag_name', object_reference) - # repo.add_tag('tag_name', object_reference, {:options => 'here'}) - # repo.add_tag('tag_name', {:options => 'here'}) # - # Options: - # :a | :annotate -> true - # :d -> true - # :f -> true - # :m | :message -> String - # :s -> true - # - def add_tag(name, *opts) - self.lib.tag(name, *opts) + # @example + # repo.add_tag('tag_name', object_reference) + # repo.add_tag('tag_name', object_reference, {:options => 'here'}) + # repo.add_tag('tag_name', {:options => 'here'}) + # + # @param [String] name The name of the tag to add + # @param [Hash] options Opstions to pass to `git tag`. + # See [git-tag](https://git-scm.com/docs/git-tag) for more details. + # @option options [boolean] :annotate Make an unsigned, annotated tag object + # @option options [boolean] :a An alias for the `:annotate` option + # @option options [boolean] :d Delete existing tag with the given names. + # @option options [boolean] :f Replace an existing tag with the given name (instead of failing) + # @option options [String] :message Use the given tag message + # @option options [String] :m An alias for the `:message` option + # @option options [boolean] :s Make a GPG-signed tag. + # + def add_tag(name, *options) + self.lib.tag(name, *options) self.tag(name) end @@ -539,9 +569,10 @@ def with_temp_working &blk # runs git rev-parse to convert the objectish to a full sha # - # @git.revparse("HEAD^^") - # @git.revparse('v2.4^{tree}') - # @git.revparse('v2.4:/doc/index.html') + # @example + # git.revparse("HEAD^^") + # git.revparse('v2.4^{tree}') + # git.revparse('v2.4:/doc/index.html') # def revparse(objectish) self.lib.revparse(objectish) diff --git a/lib/git/base/factory.rb b/lib/git/base/factory.rb index cbe5b107..7b601306 100644 --- a/lib/git/base/factory.rb +++ b/lib/git/base/factory.rb @@ -4,13 +4,13 @@ class Base module Factory - # returns a Git::Branch object for branch_name + # @return [Git::Branch] an object for branch_name def branch(branch_name = 'master') Git::Branch.new(self, branch_name) end - # returns a Git::Branches object of all the Git::Branch - # objects for this repo + # @return [Git::Branches] a collection of all the branches in the repository. + # Each branch is represented as a {Git::Branch}. def branches Git::Branches.new(self) end @@ -26,62 +26,69 @@ def worktrees Git::Worktrees.new(self) end + # @return [Git::Object::Commit] a commit object def commit_tree(tree = nil, opts = {}) Git::Object::Commit.new(self, self.lib.commit_tree(tree, opts)) end - # returns a Git::Diff object + # @return [Git::Diff] a Git::Diff object def diff(objectish = 'HEAD', obj2 = nil) Git::Diff.new(self, objectish, obj2) end - + + # @return [Git::Object] a Git object def gblob(objectish) Git::Object.new(self, objectish, 'blob') end - + + # @return [Git::Object] a Git object def gcommit(objectish) Git::Object.new(self, objectish, 'commit') end + # @return [Git::Object] a Git object def gtree(objectish) Git::Object.new(self, objectish, 'tree') end - - # returns a Git::Log object with count commits + + # @return [Git::Log] a log with the specified number of commits def log(count = 30) Git::Log.new(self, count) end - + # returns a Git::Object of the appropriate type - # you can also call @git.gtree('tree'), but that's + # you can also call @git.gtree('tree'), but that's # just for readability. If you call @git.gtree('HEAD') it will - # still return a Git::Object::Commit object. + # still return a Git::Object::Commit object. # - # @git.object calls a factory method that will run a rev-parse - # on the objectish and determine the type of the object and return - # an appropriate object for that type + # object calls a factory method that will run a rev-parse + # on the objectish and determine the type of the object and return + # an appropriate object for that type + # + # @return [Git::Object] an instance of the appropriate type of Git::Object def object(objectish) Git::Object.new(self, objectish) end - - # returns a Git::Remote object + + # @return [Git::Remote] a remote of the specified name def remote(remote_name = 'origin') Git::Remote.new(self, remote_name) end - # returns a Git::Status object + # @return [Git::Status] a status object def status Git::Status.new(self) end - - # returns a Git::Tag object + + # @return [Git::Object::Tag] a tag object def tag(tag_name) Git::Object.new(self, tag_name, 'tag', true) end # Find as good common ancestors as possible for a merge # example: g.merge_base('master', 'some_branch', 'some_sha', octopus: true) - # returns Array + # + # @return [Array] a collection of common ancestors def merge_base(*args) shas = self.lib.merge_base(*args) shas.map { |sha| gcommit(sha) } diff --git a/lib/git/lib.rb b/lib/git/lib.rb index 1aa47e5a..191b8a74 100644 --- a/lib/git/lib.rb +++ b/lib/git/lib.rb @@ -11,6 +11,43 @@ class Lib @@semaphore = Mutex.new + # The path to the Git working copy. The default is '"./.git"'. + # + # @return [Pathname] the path to the Git working copy. + # + # @see [Git working tree](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefworkingtreeaworkingtree) + # + attr_reader :git_work_dir + + # The path to the Git repository directory. The default is + # `"#{git_work_dir}/.git"`. + # + # @return [Pathname] the Git repository directory. + # + # @see [Git repository](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefrepositoryarepository) + # + attr_reader :git_dir + + # The Git index file used to stage changes (using `git add`) before they + # are committed. + # + # @return [Pathname] the Git index file + # + # @see [Git index file](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefindexaindex) + # + attr_reader :git_index_file + + # Create a new Git::Lib object + # + # @param [Git::Base, Hash] base An object that passes in values for + # @git_work_dir, @git_dir, and @git_index_file + # + # @param [Logger] logger + # + # @option base [Pathname] :working_directory + # @option base [Pathname] :repository + # @option base [Pathname] :index + # def initialize(base = nil, logger = nil) @git_dir = nil @git_index_file = nil @@ -44,9 +81,6 @@ def init(opts={}) # tries to clone the given repo # - # returns {:repository} (if bare) - # {:working_directory} otherwise - # # accepts options: # :bare:: no working directory # :branch:: name of branch to track (rather than 'master') @@ -58,6 +92,8 @@ def init(opts={}) # # TODO - make this work with SSH password or auth_key # + # @return [Hash] the options to pass to {Git::Base.new} + # def clone(repository, name, opts = {}) @path = opts[:path] || '.' clone_dir = opts[:path] ? File.join(@path, name) : name