lib/qb/repo/git.rb in qb-0.3.15 vs lib/qb/repo/git.rb in qb-0.3.16

- old
+ new

@@ -15,14 +15,11 @@ # Refinements # ======================================================================= -require 'nrser/refinements' using NRSER - -require 'nrser/refinements/types' using NRSER::Types # Declarations # ======================================================================= @@ -35,22 +32,39 @@ # ======================================================================= # Encapsulate information about a Git repository and expose useful operations as # instance methods. # -# The main entry point is {QB::Repo::Git.from_path}, which creates a +# The main entry point is {QB::Repo::Git.from_path}, which creates a # class QB::Repo::Git < QB::Repo - GITHUB_SSH_URL_RE = /^git@github\.com\:(?<owner>.*)\/(?<name>.*)\.git$/ - GITHUB_HTTPS_URL_RE = /^https:\/\/github\.com\/(?<owner>.*)\/(?<name>.*)\.git$/ + autoload :User, 'qb/repo/git/user' + autoload :GitHub, 'qb/repo/git/github' - class User < QB::Util::Resource - prop :name, type: t.maybe(t.str), default: nil - prop :email, type: t.maybe(t.str), default: nil - end + # Props + # ===================================================================== + prop :user, type: User + prop :head, type: t.maybe(t.str) + prop :branch, type: t.maybe(t.str) + prop :origin, type: t.maybe(t.str) + prop :owner, type: t.maybe(t.str) + prop :github, type: t.maybe(t.hash_) + + # Derived Properties + # --------------------------------------------------------------------- + + prop :head_short, type: t.maybe(t.str), source: :head_short + prop :full_name, type: t.maybe(t.str), source: :full_name + prop :is_github, type: t.bool, source: :github? + prop :is_clean, type: t.bool, source: :clean? + + + + + # class GitHubRemote < NRSER::Meta::Props::Base # SSH_URL_RE = /^git@github\.com\:(?<owner>.*)\/(?<name>.*)\.git$/ # HTTPS_URL_RE = /^https:\/\/github\.com\/(?<owner>.*)\/(?<name>.*)\.git$/ # # prop :owner, type: t.str @@ -62,29 +76,29 @@ # # # Class Methods # # ===================================================================== # # # Test if a Git SSH or HTTPS remote url points to GitHub. - # # + # # # # @param [String] url - # # + # # # # @return [Boolean] - # # + # # # def self.url? url # SSH_URL_RE.match(url) || HTTPS_URL_RE.match(url) # end # .url? # # # # Instantiate an instance from a Git SSH or HTTPS remote url that points # # to GitHub. - # # + # # # # @param [type] arg_name # # @todo Add name param description. - # # + # # # # @return [QB::Repo::Git::GitHubRemote] # # @todo Document return value. - # # + # # # def self.from_url url, use_api: false # match = SSH_URL_RE.match(git.origin) || # HTTPS_URL_RE.match(git.origin) # # unless match @@ -102,17 +116,17 @@ # end # .from_url # # # # # @todo Document full_name method. - # # + # # # # @param [type] arg_name # # @todo Add name param description. - # # + # # # # @return [return_type] # # @todo Document return value. - # # + # # # def full_name arg_name # "#{ owner }/#{ name }" # end # #full_name # # end @@ -137,22 +151,22 @@ # @param [Boolean] use_github_api: # When `true` will will contact the GitHub API for information to populate # the {QB::Repo::Git#github} property for repos that have a GitHub origin # URL. # - # Otherwise we will just assume GitHub repos are private since it's the - # safe guess, resulting in a {QB::Repo::Git#github} value of + # Otherwise we will just assume GitHub repos are private since it's the + # safe guess, resulting in a {QB::Repo::Git#github} value of # `{private: true}`. # # @return [QB::Repo::Git] # If `path` is in a Git repo. # # @return [nil] # If `path` is not in a Git repo. # # @raise [QB::FSStateError] - # - If we can't find any existing directory to look in based on + # - If we can't find any existing directory to look in based on # `input_path`. # def self.from_path path, use_github_api: false ref_path = path @@ -281,11 +295,11 @@ # @param use_github_api: see #from_path # # @return [QB::Repo::Git] # # @raise [QB::FSStateError] - # - If we can't find any existing directory to look in based on + # - If we can't find any existing directory to look in based on # `input_path`. # # - If the directory we do find to look in does not seems to be part of # a Git repo. # @@ -298,30 +312,10 @@ end } end # #from_path! - # Props - # ===================================================================== - - prop :user, type: User - prop :is_clean, type: t.bool - prop :head, type: t.maybe(t.str) - prop :branch, type: t.maybe(t.str) - prop :origin, type: t.maybe(t.str) - prop :owner, type: t.maybe(t.str) - prop :github, type: t.maybe(t.hash_) - - - # Derived Properties - # --------------------------------------------------------------------- - - prop :head_short, type: t.maybe(t.str), source: :head_short - prop :full_name, type: t.maybe(t.str), source: :full_name - prop :is_github, type: t.bool, source: :github? - - # Instance Methods # ===================================================================== def full_name "#{ owner }/#{ name }" if owner && name @@ -329,36 +323,58 @@ def head_short head[0...7] if head end + + # Always returns `false`, where {QB::Repo::Git::GitHub#github?} always + # returns `true`. + # + # Use {.from_path} to construct instances so you end up with the right + # class. + # + # @return [false] + # def github? - !github.nil? + # origin && QB::Repo::Git::GitHub.url?( origin ) + false end - def api + + def api @api ||= ::Git.open root_path end # Reading Repo State # --------------------------------------------------------------------- + def status + Cmds.new( 'git status --porcelain', chdir: root_path ). + out!.lines.map( &:chomp ).map { |line| + m = /\A\s*(?<mode>\S+)\s*(?<path>.*)\z/.match line + + [m['path'], m['mode']] + }.to_h + end + + # @return [Boolean] # `false` if the repo has any uncommitted changes or untracked files. # - def clean? - is_clean + def clean? ignore: nil + if ignore + ignore = [*ignore] + status.reject { |path, mode| + ignore.any? { |pattern| File.fnmatch? pattern, path } + }.empty? + else + status.empty? + end end def tags api.tags.map &:name end end # class QB::Repo::Git - - -# Post-Processing -# ======================================================================= - -require 'qb/repo/git/github'