Class: MGit::Repo::Status

Inherits:
Object
  • Object
show all
Defined in:
lib/m-git/repo/status.rb

Constant Summary collapse

FILE_STATUS =

具体规则: X Y Meaning


[AMD]   not updated

M [ MD] updated in index A [ MD] added to index D deleted from index R [ MD] renamed in index C [ MD] copied in index

MARC

index and work tree matches

MARC

M work tree changed since index

MARC

D deleted in work tree

D

R renamed in work tree

D

C copied in work tree


D D unmerged, both deleted A U unmerged, added by us U D unmerged, deleted by them U A unmerged, added by them D U unmerged, deleted by us A A unmerged, both added U U unmerged, both modified


? ? untracked ! ! ignored


{
    :unmodified     =>  ' ',
    :modified       =>  'M',
    :added          =>  'A',
    :deleted        =>  'D',
    :renamed        =>  'R',
    :copied         =>  'C'
}.freeze
FILE_STATUS_CONFLICT =
{
    :both_deleted   => 'DD',
    :we_added       => 'AU',
    :they_deleted   => 'UD',
    :they_added     => 'UA',
    :we_deleted     => 'DU',
    :both_added     => 'AA',
    :both_modified  => 'UU'
}.freeze
FILE_STATUS_SPECIAL =
{
    :untracked      => '??',
    :ignored        => '!!'
}.freeze
FILE_STATUS_MESSAGE =
{
    FILE_STATUS[:unmodified].to_s               =>  nil,
    FILE_STATUS[:modified].to_s                 => '[已修改]',
    FILE_STATUS[:added].to_s                    => '[已添加]',
    FILE_STATUS[:deleted].to_s                  => '[已删除]',
    FILE_STATUS[:renamed].to_s                  => '[重命名]',
    FILE_STATUS[:copied].to_s                   => '[已拷贝]',
    FILE_STATUS_CONFLICT[:both_deleted].to_s    => '[删除|删除]',
    FILE_STATUS_CONFLICT[:we_added].to_s        => '[添加|修改]',
    FILE_STATUS_CONFLICT[:they_deleted].to_s    => '[修改|删除]',
    FILE_STATUS_CONFLICT[:they_added].to_s      => '[修改|添加]',
    FILE_STATUS_CONFLICT[:we_deleted].to_s      => '[删除|修改]',
    FILE_STATUS_CONFLICT[:both_added].to_s      => '[添加|添加]',
    FILE_STATUS_CONFLICT[:both_modified].to_s   => '[修改|修改]',
    FILE_STATUS_SPECIAL[:untracked].to_s        => '[未跟踪]',
    FILE_STATUS_SPECIAL[:ignored].to_s          => '[被忽略]'
}.freeze
STATUS_TYPE =
{
    :normal         => 1,
    :conflicts      => 2,
    :special        => 3
}.freeze
GIT_REPO_STATUS =
{
    :clean          =>  'clean',
    :dirty          =>  'dirty'
}.freeze
GIT_REPO_STATUS_DIRTY_ZONE =
{
    :index          =>  1,      # 暂存区
    :work_tree      =>  1 << 1, # 工作区
    :special        =>  1 << 2  # 未跟踪和被ignore
}.freeze
GIT_BRANCH_STATUS =
{
    :ahead          =>  'ahead',
    :behind         =>  'behind',
    :detached       =>  'detached',
    :diverged       =>  'diverged',
    :no_remote      =>  'no_remote',
    :no_tracking    =>  'no_tracking',
    :up_to_date     =>  'up_to_date'
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Status

Returns a new instance of Status.



119
120
121
122
123
# File 'lib/m-git/repo/status.rb', line 119

def initialize(path)
  @path = path
  @status, @message = nil, nil
  @branch_status, @branch_message, @dirty_zone = nil, nil, nil
end

Instance Method Details

#branch_messageObject



145
146
147
148
# File 'lib/m-git/repo/status.rb', line 145

def branch_message
  check_branch_status if @branch_message.nil?
  return @branch_message
end

#branch_statusObject



140
141
142
143
# File 'lib/m-git/repo/status.rb', line 140

def branch_status
  check_branch_status if @branch_status.nil?
  return @branch_status
end

#commit_exist?(commit) ⇒ Boolean

commit是否存在

Returns:

  • (Boolean)


270
271
272
273
274
275
# File 'lib/m-git/repo/status.rb', line 270

def commit_exist?(commit)
  cmd = "git --git-dir=\"#{git_dir}\" --work-tree=\"#{work_tree}\" cat-file -t #{commit}"
  Utils.execute_shell_cmd(cmd) { |stdout, stderr, status|
    return status.success?
  }
end

#current_branch(strict_mode: true, use_cache: false) ⇒ String

查询当前分支

Parameters:

  • strict_mode (Boolean) (defaults to: true)

    default: true,是否是严格模式。在严格模式下,失败即终止。在非严格模式下,失败返回nil。

  • use_cache (Boolean) (defaults to: false)

    default: false,是否使用缓存

Returns:

  • (String)

    当前分支,查询失败或游离返回nil



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/m-git/repo/status.rb', line 224

def current_branch(strict_mode:true, use_cache:false)
  return @current_branch if use_cache && !@current_branch.nil?

  cmd = "git --git-dir=\"#{git_dir}\" --work-tree=\"#{work_tree}\" symbolic-ref --short -q HEAD"
  Utils.execute_shell_cmd(cmd) { |stdout, stderr, status|
    if status.success?
      @current_branch = stdout.chomp
      return @current_branch
    elsif strict_mode
      Foundation.help!("仓库#{File.basename(@path)}当前分支查询失败:当前HEAD不指向任何分支!")
    else
      return nil
    end
  }
end

#current_head(strict_mode: true) ⇒ String

查询当前HEAD指向的commit

Parameters:

  • strict_mode (Boolean) (defaults to: true)

    default: true,是否是严格模式。在严格模式下,失败即终止。在非严格模式下,失败返回nil。

Returns:

  • (String)

    commit id



246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/m-git/repo/status.rb', line 246

def current_head(strict_mode:true)
  cmd = "git --git-dir=\"#{git_dir}\" --work-tree=\"#{work_tree}\" rev-parse --short HEAD"
  Utils.execute_shell_cmd(cmd) { |stdout, stderr, status|
    if status.success?
      return stdout.chomp
    elsif strict_mode
      Foundation.help!("仓库#{File.basename(@path)}HEAD指向查询失败:#{stderr}")
    else
      return nil
    end
  }
end

#default_urlObject

查询仓库url



278
279
280
281
282
283
284
285
286
287
# File 'lib/m-git/repo/status.rb', line 278

def default_url
  cmd = "git --git-dir=\"#{git_dir}\" --work-tree=\"#{work_tree}\" config remote.origin.url"
  Utils.execute_shell_cmd(cmd) { |stdout, stderr, status|
    if status.success?
      return stdout.chomp
    else
      return nil
    end
  }
end

#dirty_zoneObject



135
136
137
138
# File 'lib/m-git/repo/status.rb', line 135

def dirty_zone
  check_repo_status if @dirty_zone.nil?
  return @dirty_zone
end

#is_ancestor_of_branch?(branch) ⇒ Boolean

当前分支是否是某个分支的祖先

Returns:

  • (Boolean)


167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/m-git/repo/status.rb', line 167

def is_ancestor_of_branch?(branch)
  c_branch = current_branch
  cmd  = "git --git-dir=\"#{git_dir}\" --work-tree=\"#{work_tree}\" merge-base --is-ancestor #{c_branch} #{branch}"
  cmd2 = "git --git-dir=\"#{git_dir}\" --work-tree=\"#{work_tree}\" rev-parse --verify #{branch}"
  cmd3 = "git --git-dir=\"#{git_dir}\" --work-tree=\"#{work_tree}\" rev-parse --verify #{c_branch}"

  is_ancestor = false
  Utils.execute_shell_cmd(cmd) { |stdout, stderr, status|
    is_ancestor = status.success?
  }

  # 当两个分支指向同一个commit的时候,“merge-base --is-ancestor”指令依然返回true,这里判断如果是这样当情况,就返回false
  if is_ancestor
    branch_hash = nil
    Utils.execute_shell_cmd(cmd2) { |stdout, stderr, status|
      branch_hash = stdout.chomp if status.success?
    }

    c_branch_hash = nil
    Utils.execute_shell_cmd(cmd3) { |stdout, stderr, status|
      c_branch_hash = stdout.chomp if status.success?
    }
    return !branch_hash.nil? && !c_branch_hash.nil? && branch_hash != c_branch_hash
  else
    return false
  end
end

#is_in_merge_progress?Boolean

是否处于merge中间态

Returns:

  • (Boolean)


151
152
153
154
155
156
# File 'lib/m-git/repo/status.rb', line 151

def is_in_merge_progress?
  cmd = "git --git-dir=\"#{git_dir}\" --work-tree=\"#{work_tree}\" merge HEAD"
  Utils.execute_shell_cmd(cmd) { |stdout, stderr, status|
    return !status.success?
  }
end

#is_in_rebase_progress?Boolean

是否处于rebase中间态

Returns:

  • (Boolean)


159
160
161
162
163
164
# File 'lib/m-git/repo/status.rb', line 159

def is_in_rebase_progress?
  cmd = "git --git-dir=\"#{git_dir}\" --work-tree=\"#{work_tree}\" rebase HEAD"
  Utils.execute_shell_cmd(cmd) { |stdout, stderr, status|
    return !status.success?
  }
end

#local_branch_exist?(branch) ⇒ Boolean

指定分支本地是否存在

Returns:

  • (Boolean)


260
261
262
# File 'lib/m-git/repo/status.rb', line 260

def local_branch_exist?(branch)
  return has_branch?(branch, false)
end

#messageObject



130
131
132
133
# File 'lib/m-git/repo/status.rb', line 130

def message
  check_repo_status if @message.nil?
  return @message
end

#refreshObject

清空所有缓存内容



290
291
292
293
294
# File 'lib/m-git/repo/status.rb', line 290

def refresh
  @status, @message = nil, nil
  @branch_status, @branch_message = nil, nil
  @dirty_zone = 0
end

#remote_branch_exist?(branch) ⇒ Boolean

指定分支是否存在对应远程分支(origin)

Returns:

  • (Boolean)


265
266
267
# File 'lib/m-git/repo/status.rb', line 265

def remote_branch_exist?(branch)
  return has_branch?(branch, true)
end

#statusObject



125
126
127
128
# File 'lib/m-git/repo/status.rb', line 125

def status
  check_repo_status if @status.nil?
  return @status
end

#tracking_branch(branch, use_cache: false) ⇒ String

查询追踪的远程分支

Parameters:

  • branch (String)

    查询分支

  • use_cache (Boolean) (defaults to: false)

    default: false,是否使用缓存

Returns:

  • (String)

    追踪的远程分支



203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/m-git/repo/status.rb', line 203

def tracking_branch(branch, use_cache:false)
  return @tracking_branch if use_cache && !@tracking_branch.nil?

  cmd = "git --git-dir=\"#{git_dir}\" --work-tree=\"#{work_tree}\" rev-parse --abbrev-ref #{branch}@{u}"
  Utils.execute_shell_cmd(cmd) { |stdout, stderr, status|
    if status.success?
      @tracking_branch = stdout.chomp
      return @tracking_branch
    end
    return nil
  }
end