├── Support
├── spec
│ ├── spec.opts
│ ├── fixtures
│ │ ├── stash_list_response_many_stashes.txt
│ │ ├── commit_result.txt
│ │ ├── status_output.txt
│ │ ├── new_line_at_end.diff
│ │ ├── small.diff
│ │ ├── conflict.txt
│ │ ├── fetch_1_5_4_3_output.txt
│ │ ├── push_1_5_4_3_output.txt
│ │ ├── config_listing.txt
│ │ ├── pull_1_5_4_3_output.txt
│ │ ├── submodules.diff
│ │ ├── log.txt
│ │ └── changed_files.diff
│ ├── run_all_spec.rb
│ ├── controllers
│ │ ├── misc_controller_spec.rb
│ │ ├── config_controller_spec.rb
│ │ ├── tag_controller_spec.rb
│ │ ├── annotate_controller_spec.rb
│ │ ├── submodule_controller_spec.rb
│ │ ├── diff_controller_spec.rb
│ │ ├── stash_controller_spec.rb
│ │ └── log_controller_spec.rb
│ ├── lib
│ │ ├── commands
│ │ │ ├── commit_spec.rb
│ │ │ ├── merge_spec.rb
│ │ │ ├── log_spec.rb
│ │ │ ├── annotate_spec.rb
│ │ │ ├── remote_spec.rb
│ │ │ ├── config_spec.rb
│ │ │ ├── status_spec.rb
│ │ │ ├── pull_spec.rb
│ │ │ ├── diff_spec.rb
│ │ │ └── push_spec.rb
│ │ ├── git_spec.rb
│ │ └── partial_commit_worker_spec.rb
│ └── spec_helper.rb
├── tmvc
│ ├── lib
│ │ ├── application_helper.rb
│ │ ├── string.rb
│ │ ├── erb_stdout.rb
│ │ ├── hash.rb
│ │ ├── format_helpers
│ │ │ └── tag_helper.rb
│ │ ├── ruby_tm_helpers.rb
│ │ └── html_helpers.rb
│ ├── spec
│ │ ├── spec_helper.rb
│ │ ├── hash_spec.rb
│ │ ├── tag_helper_spec.rb
│ │ ├── string_spec.rb
│ │ ├── spec_helpers.rb
│ │ └── html_helpers_spec.rb
│ └── tmvc.rb
├── resource
│ ├── git-logo.png
│ ├── toggle.js
│ └── rb_gateway.js
├── Gemfile
├── nibs
│ ├── CompareBranches.nib
│ │ └── keyedobjects.nib
│ └── RevisionSelector.nib
│ │ └── keyedobjects.nib
├── dispatch.rb
├── Gemfile.lock
├── lib
│ ├── commands
│ │ ├── proxy_command_base.rb
│ │ ├── svn.rb
│ │ ├── stash.rb
│ │ ├── remote.rb
│ │ ├── config.rb
│ │ └── submodule.rb
│ ├── auto_load.rb
│ ├── ui.rb
│ ├── date_helpers.rb
│ ├── stream_progress_methods.rb
│ └── partial_commit_worker.rb
├── app
│ ├── views
│ │ ├── log
│ │ │ ├── log_entries.html.erb
│ │ │ └── _log_entry.html.erb
│ │ ├── annotate
│ │ │ ├── _select_revision.html.erb
│ │ │ ├── _navigate_box.html.erb
│ │ │ ├── _content.html.erb
│ │ │ └── index.html.erb
│ │ ├── commit
│ │ │ ├── not_on_a_branch.html.erb
│ │ │ ├── _commit_result.html.erb
│ │ │ └── merge_commit.html.erb
│ │ ├── branch
│ │ │ └── merge.html.erb
│ │ ├── status
│ │ │ └── _status.html.erb
│ │ ├── submodule
│ │ │ ├── list.html.erb
│ │ │ └── index.html.erb
│ │ ├── layouts
│ │ │ └── application.html.erb
│ │ ├── diff
│ │ │ ├── _diff_results.html.erb
│ │ │ ├── _diff_check_result.html.erb
│ │ │ ├── _submodule_diff_result.html.erb
│ │ │ └── _diff_result.html.erb
│ │ └── config
│ │ │ └── index.html.erb
│ ├── controllers
│ │ ├── config_controller.rb
│ │ ├── svn_controller.rb
│ │ ├── tag_controller.rb
│ │ ├── annotate_controller.rb
│ │ ├── status_controller.rb
│ │ ├── submodule_controller.rb
│ │ ├── commit_controller.rb
│ │ ├── misc_controller.rb
│ │ ├── diff_controller.rb
│ │ └── stash_controller.rb
│ └── helpers
│ │ ├── config_helper.rb
│ │ ├── diff_helper.rb
│ │ ├── application_helper.rb
│ │ ├── annotate_helper.rb
│ │ └── submodule_helper.rb
├── gateway
│ └── commit_dialog_helper.rb
└── environment.rb
├── .gitignore
├── Preferences
├── Style: Diff.tmPreferences
├── Spell Checking: Disable.tmPreferences
├── Symbol Popup: Git Config.tmPreferences
├── Folding - Git Commit Message.tmPreferences
├── Symbol Popup: Git Config Subsection.tmPreferences
└── Comments: Git Config.tmPreferences
├── Commands
├── Use Git-Gui.tmCommand
├── Use GitX.tmCommand
├── Start Gitk.tmCommand
├── Use Gitnub.tmCommand
├── SVN Fetch.tmCommand
├── SVN Rebase.tmCommand
├── SVN Dcommit.tmCommand
├── Commit.tmCommand
├── Status.tmCommand
├── Show Log.tmCommand
├── Pull.tmCommand
├── Create Tag.tmCommand
├── Fetch.tmCommand
├── Stash.tmCommand
├── Git Init.tmCommand
├── Merge.tmCommand
├── Outgoing.tmCommand
├── Clear Stash.tmCommand
├── Push.tmCommand
├── Show Stash.tmCommand
├── Submodules.tmCommand
├── Add files to the index.tmCommand
├── Config.tmCommand
├── Create Branch.tmCommand
├── Delete Branch.tmCommand
├── Amend Last Commit.tmCommand
├── Browse Annotated File (blame).tmCommand
├── Pop Stash.tmCommand
├── Switch to Branch.tmCommand
├── Compare Revisions.tmCommand
├── Edit Conflicted File.tmCommand
├── Show Uncommitted Changes.tmCommand
├── Fixup!.tmCommand
├── Revert.tmCommand
├── Compare Branches.tmCommand
└── Git Resolve Conflicts.tmCommand
├── MIT-LICENSE
├── Macros
└── Next Rebase Command.tmMacro
├── Syntaxes
└── Git Rebase Message.tmLanguage
├── TODO
└── README.textile
/Support/spec/spec.opts:
--------------------------------------------------------------------------------
1 | --color
2 | --reverse
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /scratchpad.rb
2 | /Support/DEBUG
3 | /Support/log
--------------------------------------------------------------------------------
/Support/tmvc/lib/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | include HtmlHelpers
3 | end
4 |
--------------------------------------------------------------------------------
/Support/resource/git-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/textmate/git.tmbundle/master/Support/resource/git-logo.png
--------------------------------------------------------------------------------
/Support/spec/fixtures/stash_list_response_many_stashes.txt:
--------------------------------------------------------------------------------
1 | stash@{0}: On master: boogy
2 | stash@{1}: On master: oogity
3 |
--------------------------------------------------------------------------------
/Support/spec/run_all_spec.rb:
--------------------------------------------------------------------------------
1 | Dir.glob(File.dirname(__FILE__) + "/**/*_spec.rb").each do |file|
2 | require file
3 | end
--------------------------------------------------------------------------------
/Support/spec/fixtures/commit_result.txt:
--------------------------------------------------------------------------------
1 | Created commit 24ff719: work done
2 | 1 files changed, 1 insertions(+), 0 deletions(-)
3 |
--------------------------------------------------------------------------------
/Support/tmvc/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | SPEC_ROOT = File.dirname(__FILE__)
2 |
3 | require SPEC_ROOT + "/../tmvc.rb"
4 | require SPEC_ROOT + "/spec_helpers.rb"
--------------------------------------------------------------------------------
/Support/Gemfile:
--------------------------------------------------------------------------------
1 | # This Gemfile is needed only for running the specs
2 | source "https://rubygems.org"
3 |
4 | gem "rspec", "~> 1.3"
5 | gem "hpricot"
6 |
--------------------------------------------------------------------------------
/Support/nibs/CompareBranches.nib/keyedobjects.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/textmate/git.tmbundle/master/Support/nibs/CompareBranches.nib/keyedobjects.nib
--------------------------------------------------------------------------------
/Support/dispatch.rb:
--------------------------------------------------------------------------------
1 | $dispatch_loaded = true
2 | require File.dirname(__FILE__) + "/environment.rb"
3 |
4 | dispatch(ARGV) if $0 == __FILE__ && ! $dispatched
5 |
--------------------------------------------------------------------------------
/Support/nibs/RevisionSelector.nib/keyedobjects.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/textmate/git.tmbundle/master/Support/nibs/RevisionSelector.nib/keyedobjects.nib
--------------------------------------------------------------------------------
/Support/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | hpricot (0.8.6)
5 | rspec (1.3.2)
6 |
7 | PLATFORMS
8 | ruby
9 |
10 | DEPENDENCIES
11 | hpricot
12 | rspec (~> 1.3)
13 |
--------------------------------------------------------------------------------
/Support/spec/fixtures/status_output.txt:
--------------------------------------------------------------------------------
1 | A new_file_and_added.txt
2 | R lib/formatters/commit/layout.html.erb -> app/views/layouts/application.html.erb
3 | M project.txt
4 | D small.diff
5 | ?? dir/
6 | ?? directory.txt
7 |
--------------------------------------------------------------------------------
/Support/lib/commands/proxy_command_base.rb:
--------------------------------------------------------------------------------
1 | module SCM
2 | class Git
3 | class CommandProxyBase
4 | attr_accessor :base
5 | def initialize(base)
6 | @base = base
7 | end
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/Support/app/views/log/log_entries.html.erb:
--------------------------------------------------------------------------------
1 |
Log entries
2 |
3 | <% @log_entries.each do |log_entry| %>
4 | <% render("_log_entry", :locals => {:git => git, :log_entry => log_entry, :branch_name => @branch_name, :path => @path }) %>
5 | <% flush %>
6 | <% end %>
7 |
--------------------------------------------------------------------------------
/Support/spec/fixtures/new_line_at_end.diff:
--------------------------------------------------------------------------------
1 | diff --git a/hey hey.rb b/hey hey.rb
2 | index 477c371..19dbd58 100644
3 | --- a/hey hey.rb
4 | +++ b/hey hey.rb
5 | @@ -10,5 +10,4 @@ asdf
6 |
7 | asdf
8 |
9 | -
10 | -asdf
11 | \ No newline at end of file
12 | +boogy!
13 |
--------------------------------------------------------------------------------
/Support/spec/fixtures/small.diff:
--------------------------------------------------------------------------------
1 | diff --git a/project.txt b/project.txt
2 | index ea4f9ca..b1b35ce 100644
3 | --- a/project.txt
4 | +++ b/project.txt
5 | @@ -1 +1,3 @@
6 | -\\
7 | \ No newline at end of file
8 | +\\
9 | +
10 | +asdf
11 | \ No newline at end of file
12 |
--------------------------------------------------------------------------------
/Support/spec/fixtures/conflict.txt:
--------------------------------------------------------------------------------
1 | class Coso
2 | include Something
3 |
4 | <<<<<<< HEAD:app/models/conflicted.rb
5 | def self.method
6 | @value ||= "boogy"
7 | end
8 |
9 | =======
10 | cattr_accessor :method
11 | >>>>>>> master:app/models/conflicted.rb
12 |
13 | end
--------------------------------------------------------------------------------
/Support/app/views/annotate/_select_revision.html.erb:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Support/lib/commands/svn.rb:
--------------------------------------------------------------------------------
1 | class SCM::Git::Svn < SCM::Git::CommandProxyBase
2 |
3 | def dcommit
4 | base.command("svn","dcommit")
5 | end
6 |
7 | def fetch
8 | base.command("svn","fetch")
9 | end
10 |
11 | def rebase
12 | base.command("svn","rebase")
13 | end
14 | end
--------------------------------------------------------------------------------
/Support/app/controllers/config_controller.rb:
--------------------------------------------------------------------------------
1 | class ConfigController < ApplicationController
2 | include ConfigHelper
3 | def index
4 | render "index"
5 | end
6 |
7 | def set
8 | value = params[:value]
9 | git.config[(params[:scope] || "local"), params[:key]] = params[:value]
10 | end
11 | end
--------------------------------------------------------------------------------
/Support/app/views/commit/not_on_a_branch.html.erb:
--------------------------------------------------------------------------------
1 | Eegad! You're not on a branch
2 |
3 | To make this commit, first checkout the branch you'd like to commit to, then make the commit.
4 |
5 | Suggested branches:
6 | <%= git.command("branch", "--contains", "HEAD", "-a").gsub(/^.+no branch.*$/, "") %>
--------------------------------------------------------------------------------
/Support/app/helpers/config_helper.rb:
--------------------------------------------------------------------------------
1 | module ConfigHelper
2 | def config_text_field(local_or_global, config_key, options = {})
3 | content_tag :input, {:type => "text", :value => git.config[local_or_global, config_key], :onchange => "dispatch({controller: 'config', action: 'set', scope: '#{local_or_global}', key: '#{config_key}', value: $F(this)})"}.merge(options)
4 | end
5 | end
--------------------------------------------------------------------------------
/Support/spec/fixtures/fetch_1_5_4_3_output.txt:
--------------------------------------------------------------------------------
1 | remote: Counting objects: 5, done.[K
2 | remote: Compressing objects: 33% (1/3) [K
remote: Compressing objects: 66% (2/3) [K
remote: Compressing objects: 100% (3/3) [K
remote: Compressing objects: 100% (3/3), done.[K
3 | remote: Total 3 (delta 2), reused 0 (delta 0)[K
4 | From ../satellite
5 | 74c0fdf..d1c6bdd asdf -> satellite/asdf
6 |
--------------------------------------------------------------------------------
/Support/tmvc/lib/string.rb:
--------------------------------------------------------------------------------
1 | class String
2 | def constantize
3 | Object.module_eval("::" + self)
4 | end
5 |
6 | def underscore
7 | gsub(/(^|\b)[A-Z]/) { |l| l.downcase}.gsub(/[A-Z]/) { |l| "_#{l.downcase}" }.gsub("::", "/")
8 | end
9 |
10 | def classify
11 | gsub(/^[a-z]/) { |l| l.upcase}.gsub(/_[a-z]/) { |l| l[1..1].upcase}.gsub(/\b[a-z]/) {|l| l.upcase}.gsub("/", "::")
12 | end
13 | end
--------------------------------------------------------------------------------
/Support/app/views/branch/merge.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= @result[:text] %>
3 |
4 |
5 | <% unless @result[:conflicts].empty? %>
6 | Conflicts - resolve each of the following then commit:
7 | <% @result[:conflicts].each do |conflicted_file| %>
8 | <% full_path = File.join(git.path, conflicted_file) %>
9 |
10 | <%= link_to_textmate conflicted_file, full_path %>
11 |
12 | <% end %>
13 | <% end %>
14 |
--------------------------------------------------------------------------------
/Support/spec/controllers/misc_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 |
3 | describe MiscController do
4 | include SpecHelpers
5 |
6 | before(:each) do
7 | @git = Git.singleton_new
8 | end
9 |
10 | it "should initialize a repository" do
11 | @git.should_receive(:init)
12 | output = capture_output do
13 | dispatch(:controller => "misc", :action => "init");
14 | end
15 | end
16 | end
--------------------------------------------------------------------------------
/Support/app/helpers/diff_helper.rb:
--------------------------------------------------------------------------------
1 | module DiffHelper
2 | def extract_submodule_revisions(diff_result)
3 | diff_result[:lines].map do |line|
4 | line[:text].gsub("Subproject commit ", "")
5 | end
6 | end
7 |
8 | def htmlize_highlight_trailing_whitespace (text)
9 | if text =~ /[ \t]+$/
10 | htmlize($`) + content_tag(:span, $&, :class => "trailing-whitespace")
11 | else
12 | htmlize(text)
13 | end
14 | end
15 | end
--------------------------------------------------------------------------------
/Support/app/controllers/svn_controller.rb:
--------------------------------------------------------------------------------
1 | class SvnController < ApplicationController
2 | def dcommit
3 | puts "Committing to Subversion Repository "
4 | puts htmlize(git.svn.dcommit)
5 | end
6 |
7 | def rebase
8 | puts "Rebasing Subversion Repository "
9 | puts htmlize(git.svn.rebase)
10 | end
11 |
12 | def fetch
13 | puts "Fetching Subversion Repository "
14 | puts htmlize(git.svn.fetch)
15 | end
16 |
17 | end
--------------------------------------------------------------------------------
/Support/tmvc/spec/hash_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + "/spec_helper.rb"
2 |
3 | describe Hash do
4 | it "should stringify_keys" do
5 | h = {:author => 1, "date" => 1}
6 | h.stringify_keys!
7 | h.keys.sort.should == ["author", "date"]
8 | end
9 |
10 | it "should filter the keys" do
11 | {:a => 1, :b => 2}.filter(:a).should == {:a => 1}
12 | end
13 |
14 | it "should reject specified keys" do
15 | {:a => 1, :b => 2}.reject(:b).should == {:a => 1}
16 | end
17 | end
--------------------------------------------------------------------------------
/Support/gateway/commit_dialog_helper.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby18
2 | require File.dirname(__FILE__) + '/../environment.rb'
3 | git = Git.new
4 | command = ARGV.shift
5 | case command
6 | when "delete"
7 | file_path = ARGV.shift
8 | File.delete(git.path_for(file_path))
9 | puts "\000 #{file_path}asdf"
10 | when "revert"
11 | file_path = ARGV.shift
12 | File.open("#{ENV['TMPDIR']}/output", "wb") {|f| f.puts ARGV.inspect}
13 | git.revert(file_path)
14 | puts "\000 #{file_path}"
15 | end
16 |
17 |
--------------------------------------------------------------------------------
/Support/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | def short_rev(rev)
3 | rev.to_s[0..7]
4 | end
5 |
6 | def git
7 | @git ||= Git.new
8 | end
9 |
10 | def link_to_relative_file(git, file_path, line = nil, title = nil)
11 | if line
12 | link_to_textmate(title || git.root_relative_path_for(file_path), git.path_for(file_path), line)
13 | else
14 | link_to_mate(title || git.root_relative_path_for(file_path), git.path_for(file_path))
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/Support/spec/fixtures/push_1_5_4_3_output.txt:
--------------------------------------------------------------------------------
1 | Counting objects: 5, done.
2 | Compressing objects: 50% (1/2)
Compressing objects: 100% (2/2)
Compressing objects: 100% (2/2), done.
3 | Writing objects: 33% (1/3)
Writing objects: 66% (2/3)
Writing objects: 100% (3/3)
Writing objects: 100% (3/3), 268 bytes, done.
4 | Total 3 (delta 1), reused 0 (delta 0)
5 | To ../satellite/
6 | 865f920..f9ca10d asdf -> asdf
7 | ! [rejected] master -> master (non-fast forward)
8 | error: failed to push some refs to '../satellite/'
9 |
--------------------------------------------------------------------------------
/Preferences/Style: Diff.tmPreferences:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | name
6 | Style: Diff
7 | scope
8 | text.git-commit source.diff
9 | settings
10 |
11 | softWrap
12 |
13 |
14 | uuid
15 | EFA849A8-00DF-4D9A-BA37-504323969746
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Preferences/Spell Checking: Disable.tmPreferences:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | name
6 | Spell Checking: Disable
7 | scope
8 | meta.scope.metadata.git-commit
9 | settings
10 |
11 | spellChecking
12 | 0
13 |
14 | uuid
15 | 5CF68FFF-6562-4A58-8056-6034EF93E88A
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Support/app/views/commit/_commit_result.html.erb:
--------------------------------------------------------------------------------
1 | Result:
2 |
3 | <%= htmlize(result[:output]) %>
4 |
5 | Commit Files:
6 |
7 | <% files.each do |e| %>
8 | <%= htmlize(e) %>
9 | <% end %>
10 |
11 |
12 | Using Message:
13 | <%= htmlize_attr(message) %>
14 |
15 | <% if result[:rev] %>
16 | Diff of committed changes:
17 | <% render_component(:controller => "diff", :action => "diff", :path => ".", :revisions => "#{result[:rev]}^..#{result[:rev]}") %>
18 | <% end %>
19 |
--------------------------------------------------------------------------------
/Preferences/Symbol Popup: Git Config.tmPreferences:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | name
6 | Symbol Popup: Git Config Section
7 | scope
8 | entity.name.section.git-config
9 | settings
10 |
11 | showInSymbolList
12 | 1
13 |
14 | uuid
15 | 3E646038-6F79-46BE-96A3-9802E7011162
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Support/lib/auto_load.rb:
--------------------------------------------------------------------------------
1 | module AutoLoad
2 | def const_missing(name)
3 | name = name.to_s
4 | case name
5 | when /Controller$/
6 | path = "/app/controllers"
7 | when /Helper$/
8 | path = "/app/helpers"
9 | else
10 | return super
11 | end
12 |
13 | @last_try||=nil
14 | super if @last_try==name
15 | @last_try = name
16 |
17 | file = File.join(ROOT, path, name.to_s.underscore + ".rb")
18 | require file
19 | name.constantize
20 | klass = const_get(name)
21 | rescue LoadError
22 | super
23 | end
24 | end
25 |
26 | Object.send :extend, AutoLoad
--------------------------------------------------------------------------------
/Preferences/Folding - Git Commit Message.tmPreferences:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | name
6 | Folding (Git Commit Message)
7 | scope
8 | text.git-commit
9 | settings
10 |
11 | foldingStartMarker
12 | ^\+\+\+
13 | foldingStopMarker
14 | ^---
15 |
16 | uuid
17 | 1A0DB209-7219-4BA5-BB32-3A282919890B
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Support/tmvc/spec/tag_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + "/spec_helper.rb"
2 | describe FormatHelpers::TagHelper do
3 | include SpecHelpers
4 |
5 | it "should return a formatted tag in non-block notation" do
6 | content_tag(:script, "", :type => "javascript", :src => "prototype.js").should == ""
7 | end
8 |
9 | it "should output the tag with the block contents in the middle" do
10 | output = capture_output do
11 | content_tag(:p) do
12 | STDOUT << "Content"
13 | end
14 | end
15 |
16 | output.should == "Content
"
17 | end
18 | end
--------------------------------------------------------------------------------
/Support/tmvc/lib/erb_stdout.rb:
--------------------------------------------------------------------------------
1 | require 'erb'
2 |
3 | class ERBStdout < ERB
4 | def set_eoutvar(compiler, eoutvar = 'STDOUT')
5 | compiler.put_cmd = "#{eoutvar} << "
6 | compiler.insert_cmd = "#{eoutvar} << " if compiler.respond_to?(:insert_cmd)
7 | compiler.pre_cmd = "#{eoutvar}.flush"
8 | compiler.post_cmd = "#{eoutvar}.flush; ''"
9 |
10 | if RUBY_VERSION >= "1.9"
11 | # in Ruby1.9.x, ERB wants pre_cmd/post_cmd wrapped in Array
12 | compiler.pre_cmd = [compiler.pre_cmd]
13 | compiler.post_cmd = [compiler.post_cmd]
14 | end
15 | end
16 |
17 | def run(b=TOPLEVEL_BINDING)
18 | self.result(b)
19 | end
20 | end
21 |
22 |
--------------------------------------------------------------------------------
/Support/tmvc/lib/hash.rb:
--------------------------------------------------------------------------------
1 | class Hash
2 | def filter(*keys)
3 | keys.flatten.inject({}) do |new_hash, key|
4 | new_hash[key] = self[key] if self[key]
5 | new_hash
6 | end
7 | end
8 |
9 | def stringify_keys!
10 | keys.each do |k|
11 | if k.is_a?(Symbol)
12 | value = delete(k)
13 | self[k.to_s] = value
14 | end
15 | end
16 | end
17 |
18 | unless method_defined?(:reject_without_params)
19 | alias reject_without_params reject
20 | def reject(*keys, &block)
21 | return reject_without_params(&block) if keys.empty?
22 | reject_without_params { |key,value| keys.include?(key)}
23 | end
24 | end
25 | end
--------------------------------------------------------------------------------
/Support/app/views/status/_status.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <% status_data.each do |e| %>
3 |
4 |
5 |
6 | <%= htmlize(e[:status][:short]) %>
7 |
8 |
9 |
10 | <% if e[:path][-1..-1]=="/" %>
11 | <%= htmlize(git.root_relative_path_for(e[:display])) %>
12 | <% else %>
13 | <%= link_to_relative_file(git, e[:path]) %>
14 | <% end %>
15 |
16 |
17 | <% end %>
18 |
--------------------------------------------------------------------------------
/Support/spec/fixtures/config_listing.txt:
--------------------------------------------------------------------------------
1 | alias.co=checkout
2 | alias.b=branch
3 | branch.autosetupmerge=true
4 | user.email=timcharper@email.com
5 | user.name=Tim Harper
6 | gui.matchtrackingbranch=true
7 | core.repositoryformatversion=0
8 | core.filemode=true
9 | core.bare=false
10 | core.logallrefupdates=true
11 | remote.origin.url=../origin/
12 | remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
13 | branch.master.merge=refs/heads/master
14 | remote.satellite.url=../satellite
15 | remote.satellite.fetch=+refs/heads/*:refs/remotes/satellite/*
16 | branch.satellite.remote=satellite
17 | branch.satellite.merge=refs/heads/satellite
18 | branch.mybranch.remote=satellite
19 | branch.mybranch.merge=refs/heads/mybranch
20 |
--------------------------------------------------------------------------------
/Support/lib/ui.rb:
--------------------------------------------------------------------------------
1 | require ENV['TM_SUPPORT_PATH'] + '/lib/ui.rb'
2 |
3 | class << TextMate::UI
4 | def request_item_with_force_pick(options = {}, &block)
5 | if options[:force_pick]
6 | options[:items] << "" if options[:items].length == 1
7 | end
8 |
9 | request_item_without_force_pick(options, &block)
10 | end
11 | alias_method_chain :request_item, :force_pick
12 |
13 | def request_directory(title = "Select a directory", options = {})
14 | options[:initial_directory] ||= ENV['TM_PROJECT_DIRECTORY'] || ENV['TM_FILEPATH']
15 | result = `CocoaDialog fileselect --select-only-directories --with-directory "#{options[:initial_directory]}" --title "#{title}"`
16 | result.empty? ? nil : result.strip
17 | end
18 | end
--------------------------------------------------------------------------------
/Support/app/views/submodule/list.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Status
6 | Name
7 | Revision
8 | Tag
9 |
10 |
11 |
12 | <% @submodules.each do |submodule| %>
13 |
14 | <%= submodule.modified? ? "M" : "" %>
15 | <%= link_to_mate submodule.name, File.join(git.path, submodule.name) %>
16 | <%= git.short_rev(submodule.current_revision) %>
17 | <%= submodule.current_revision_description %>
18 |
19 | <% end %>
20 | <% if @submodules.empty? %>
21 |
22 | No submodules defined.
23 |
24 | <% end %>
25 |
26 |
--------------------------------------------------------------------------------
/Preferences/Symbol Popup: Git Config Subsection.tmPreferences:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | name
6 | Symbol Popup: Git Config Subsection
7 | scope
8 | entity.name.section.subsection.git-config - punctuation.definition.section.subsection
9 | settings
10 |
11 | showInSymbolList
12 | 1
13 | symbolTransformation
14 |
15 | s/^/ /; # indent subsections
16 |
17 |
18 | uuid
19 | E6D2DCFE-A40D-4BF1-9B43-7E3199CF00B4
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Support/app/views/commit/merge_commit.html.erb:
--------------------------------------------------------------------------------
1 | Resolve a merge conflict
2 |
3 | <% if @status.any? {|status_options| status_options[:status][:short] == "C"} %>
4 | You still have outstanding merge conflicts. Resolve them, and try to commit again.
5 | <% else %>
6 | Commit the result of a merge conflict
7 |
8 |
Message:
9 |
10 |
11 |
12 |
13 |
14 |
15 | <% end %>
16 |
--------------------------------------------------------------------------------
/Support/tmvc/spec/string_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + "/spec_helper.rb"
2 | describe String do
3 | it "should classify a string with a /" do
4 | "controllers/application_controller".classify.should == "Controllers::ApplicationController"
5 | end
6 |
7 | it "should classify a string" do
8 | "application_controller".classify.should == "ApplicationController"
9 | end
10 |
11 | it "should underscore a string" do
12 | "ApplicationController".underscore.should == "application_controller"
13 | end
14 |
15 | it "should underscore a string with a ::" do
16 | "Controllers::ApplicationController".underscore.should == "controllers/application_controller"
17 | end
18 |
19 | it "should constantize a string" do
20 | "String".constantize.should == String
21 | end
22 | end
--------------------------------------------------------------------------------
/Support/spec/fixtures/pull_1_5_4_3_output.txt:
--------------------------------------------------------------------------------
1 | remote: Counting objects: 8, done.
2 | remote: Compressing objects: 16% (1/6)
3 | remote: Compressing objects: 33% (2/6)
4 | remote: Compressing objects: 50% (3/6)
5 | remote: Compressing objects: 66% (4/6)
6 | remote: Compressing objects: 83% (5/6)
7 | remote: Compressing objects: 100% (6/6)
8 | remote: Compressing objects: 1 0remote: 0% (6/6), done.
9 | remote: Total 6 (delta 4), reused 0 (delta 0)
10 | From ../satellite
11 | dc29d3d..05f9ad9 asdf -> satellite/asdf
12 | 791a587..4bfc230 master -> satellite/master
13 | Updating 791a587..4bfc230
14 | Fast forward
15 | project.txt | 12 ++++++++++++
16 | 1 files changed, 12 insertions(+), 0 deletions(-)
17 |
--------------------------------------------------------------------------------
/Support/spec/lib/commands/commit_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../spec_helper'
2 |
3 | describe Git do
4 | before(:each) do
5 | @commit = Git.new
6 | Git.reset_mock!
7 | end
8 | include SpecHelpers
9 |
10 | it "should parse a commit" do
11 | Git.command_output << <<-EOF
12 | Created commit ff4ba93: some message
13 | 1 files changed, 2 insertions(+), 0 deletions(-)
14 | Unrecognized line
15 | EOF
16 | # @commit.should_receive(:command).and_return(commit_output)
17 |
18 | result = @commit.commit("some message")
19 | result[:rev].should == "ff4ba93"
20 | result[:message].should == "some message"
21 | result[:insertions].should == 2
22 | result[:deletions].should == 0
23 | result[:files_changed].should == 1
24 | result[:output].should == "Unrecognized line\n"
25 | end
26 | end
--------------------------------------------------------------------------------
/Support/app/controllers/tag_controller.rb:
--------------------------------------------------------------------------------
1 | require ENV['TM_SUPPORT_PATH'] + '/lib/ui.rb'
2 |
3 | class TagController < ApplicationController
4 | def create
5 | if ! (name = prompt_tag_name)
6 | puts "Aborted"
7 | return
8 | end
9 |
10 | if git.create_tag(name) == true
11 | puts "Tag #{name} created"
12 | flush
13 | render_component(:controller => "remote", :action => "push_tag", :tag => name) if prompt_want_to_push_remote
14 | end
15 | end
16 |
17 | def prompt_tag_name
18 | TextMate::UI.request_string(:title => "Create Tag", :prompt => "Enter the name of the new tag:")
19 | end
20 |
21 | def prompt_want_to_push_remote
22 | TextMate::UI.alert(:warning, "Push tag to remote servers", "Would you like to push this tag to your remote repository(s)", 'Yes', 'No') == "Yes"
23 | end
24 |
25 | end
--------------------------------------------------------------------------------
/Support/app/views/submodule/index.html.erb:
--------------------------------------------------------------------------------
1 | <%= content_tag :h1, "Submodules on branch ‘#{git.branch.current_name}’"%>
2 |
3 |
4 | <% render_component(:controller => "submodule", :action => "list", :layout => false) %>
5 |
6 | <%= button_to_remote("Add...", :params => {:controller => "submodule", :action => "add" },
7 | :on_complete => remote_function(:params => {:controller => "submodule", :action => "list"}, :update => "submodules"),
8 | :update_streaming => "iframe_output")
9 | %>
10 |
11 | <%= button_to_remote("Force Update", :params => {:controller => "submodule", :action => "update" },
12 | :on_complete => remote_function(:params => {:controller => "submodule", :action => "list"}, :update => "submodules"),
13 | :update_streaming => "iframe_output")
14 | %>
15 |
16 |
--------------------------------------------------------------------------------
/Preferences/Comments: Git Config.tmPreferences:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | name
6 | Comments: Git Config
7 | scope
8 | source.git-config
9 | settings
10 |
11 | shellVariables
12 |
13 |
14 | name
15 | TM_COMMENT_START
16 | value
17 | #
18 |
19 |
20 | name
21 | TM_COMMENT_START_2
22 | value
23 | ;
24 |
25 |
26 |
27 | uuid
28 | 1E1882B3-9578-427F-9EF8-3C56EF407F13
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Support/spec/fixtures/submodules.diff:
--------------------------------------------------------------------------------
1 | diff --git a/vendor/plugins/module1 b/vendor/plugins/module1
2 | new file mode 160000
3 | index 0000000..db01d91
4 | --- /dev/null
5 | +++ b/vendor/plugins/module1
6 | @@ -0,0 +1 @@
7 | +Subproject commit db01d91c2039ca271c7df9bcc4cacf7e949d74c2
8 | diff --git a/vendor/plugins/railswhere b/vendor/plugins/railswhere
9 | deleted file mode 160000
10 | index b9276ab..0000000
11 | --- a/vendor/plugins/railswhere
12 | +++ /dev/null
13 | @@ -1 +0,0 @@
14 | -Subproject commit b9276ab1ad9aee7c3688b365072fe0a616b68b71
15 | diff --git a/vendor/plugins/manage_fixtures b/vendor/plugins/manage_fixtures
16 | index 8379713..30f3d85 160000
17 | --- a/vendor/plugins/manage_fixtures
18 | +++ b/vendor/plugins/manage_fixtures
19 | @@ -1 +1 @@
20 | -Subproject commit 837971332a4e914a1ae3e5defd0f1d00883232df
21 | +Subproject commit 30f3d850901500b52fa70ba1aa31a8f9b9a3d3f6
22 |
--------------------------------------------------------------------------------
/Support/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 | <% script_tag = javascript_include_tag("prototype", "rb_gateway", "toggle") %>
2 |
3 |
4 |
5 |
6 | <% if @script_at_top %>
7 | <%= script_tag %>
8 | <% end %>
9 |
10 |
11 |
12 | <% yield %>
13 |
14 |
15 | <% unless @script_at_top %>
16 | <%= script_tag %>
17 | <% end %>
18 | <%= @content_for_javascript %>
19 | <% if params[:on_complete] %>
20 |
25 | <% end %>
26 |
27 |
--------------------------------------------------------------------------------
/Support/spec/controllers/config_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 |
3 | describe ConfigController do
4 | include SpecHelpers
5 | include Parsers
6 |
7 | before(:each) do
8 | @controller = ConfigController.singleton_new
9 | @git = Git.singleton_new
10 | end
11 |
12 | describe "when setting values" do
13 | it "should default to local" do
14 | @git.config.should_receive(:[]=).with("local", "user.name", "My Name")
15 | capture_output { dispatch(:controller => "config", :action => "set", :key => "user.name", :value => "My Name" )}
16 | end
17 |
18 | it "should allow setting of global variables" do
19 | @git.config.should_receive(:[]=).with("global", "user.name", "My Name")
20 | capture_output { dispatch(:controller => "config", :action => "set", :scope => "global", :key => "user.name", :value => "My Name" )}
21 | end
22 | end
23 |
24 | end
--------------------------------------------------------------------------------
/Support/spec/controllers/tag_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 |
3 | describe TagController do
4 | include SpecHelpers
5 | include Parsers
6 |
7 | before(:each) do
8 | @controller = TagController.singleton_new
9 | @git = Git.singleton_new
10 | end
11 |
12 | it "should allow you to abort" do
13 | @controller.should_receive(:prompt_tag_name).and_return(false)
14 | capture_output { dispatch :controller => "tag", :action => "create" }.should include("Aborted")
15 | end
16 |
17 | it "should not push the tag if prompt_want_to_push_remote returns false" do
18 | @controller.should_receive(:prompt_tag_name).and_return("mytab")
19 | @git.should_receive(:create_tag).and_return(true)
20 | @controller.should_receive(:prompt_want_to_push_remote).and_return(false)
21 | @controller.should_not_receive(:render_component)
22 |
23 | capture_output { dispatch :controller => "tag", :action => "create" }
24 | end
25 | end
--------------------------------------------------------------------------------
/Support/app/helpers/annotate_helper.rb:
--------------------------------------------------------------------------------
1 | module AnnotateHelper
2 | def selected_line_range
3 | lines = parse_selection_string(ENV['TM_SELECTION']).flatten
4 | [lines.min, lines.max]
5 | end
6 |
7 | # Parses the selection string and includes an array containing the lines
8 | # selected in the document
9 | def parse_selection_string(str)
10 | str.split('&').map do |range|
11 | if range =~ /(\d+)(?::(\d+))?(?:\+\d+)?(?:([-x])(\d+)(?::(\d+))?(?:\+\d+)?)?/
12 | l1, l2, c1, c2 = $1.to_i, ($4 ? $4.to_i : nil), ($2 || 1).to_i, ($5 || 1).to_i
13 | l1, l2, c1, c2 = l2, l1, c2, c1 if l2 && (l1 > l2 || l1 == l2 && c1 > c2)
14 |
15 | case $3
16 | when 'x'
17 | [ l1, l2 ]
18 | when '-'
19 | l2 -= 1 if c2 == 1
20 | [ l1, l2 ]
21 | else
22 | [ l1, l1 ]
23 | end
24 | else
25 | abort "unsupported selection string syntax: ‘#{range}’"
26 | end
27 | end
28 | end
29 | end
--------------------------------------------------------------------------------
/Support/app/views/diff/_diff_results.html.erb:
--------------------------------------------------------------------------------
1 | <% @diff_line_count = 0 %>
2 | <% revision ||= nil %>
3 |
4 | <% if not (diff_check_results||=[]).empty? %>
5 | <% diff_check_results.each do |diff_result| %>
6 | <% render "diff/_diff_check_result", :locals => {:git => git, :diff_result => diff_result } %>
7 | <% flush %>
8 | <% end %>
9 | <% end %>
10 | <% diff_results.each do |diff_result| %>
11 | <% next if @diff_line_count >= Git::DEFAULT_DIFF_LIMIT %>
12 | <% if diff_result[:mode] == Git::SUBMODULE_MODE %>
13 | <% render "diff/_submodule_diff_result", :locals => {:git => git, :diff_result => diff_result, :revision => revision } %>
14 | <% else %>
15 | <% render "diff/_diff_result", :locals => {:git => git, :diff_result => diff_result, :revision => revision } %>
16 | <% end %>
17 | <% flush %>
18 | <% end %>
19 |
20 | <% if @diff_line_count >= Git::DEFAULT_DIFF_LIMIT %>
21 | Diff taking to long to render... aborted
22 | <% end %>
--------------------------------------------------------------------------------
/Commands/Use Git-Gui.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
10 | dispatch(:controller => "misc", :action => "gitgui")
11 | input
12 | selection
13 | inputFormat
14 | text
15 | name
16 | Open Git-Gui
17 | outputCaret
18 | afterOutput
19 | outputFormat
20 | text
21 | outputLocation
22 | discard
23 | scope
24 | attr.scm.git
25 | uuid
26 | D0DF4B19-F311-48CC-BF68-F8B33CD051D3
27 | version
28 | 2
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Support/spec/lib/commands/merge_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../spec_helper'
2 |
3 | describe Git do
4 | before(:each) do
5 | @merge = Git.new
6 | end
7 |
8 | include SpecHelpers
9 |
10 | it "should extract conflicts from a merge" do
11 | result = @merge.parse_merge(<<-EOF)
12 | Auto-merged project.txt
13 | CONFLICT (content): Merge conflict in project.txt
14 | Auto-merged dude.txt
15 | CONFLICT (add/add): Merge conflict in dude.txt
16 | CONFLICT (delete/modify): lib/file.rb deleted in HEAD and modified in release. Version release of lib/file.rb left in tree.
17 | Auto-merged spec/fixtures/events.yml
18 | CONFLICT (delete/modify): coso.txt deleted in release and modified in HEAD. Version HEAD of coso.txt left in tree.
19 | Automatic merge failed; fix conflicts and then commit the result.
20 | Automatic merge failed; fix conflicts and then commit the result.
21 | EOF
22 | # puts result.inspect
23 | result[:conflicts].should == ["project.txt", "dude.txt", "lib/file.rb", "coso.txt"]
24 | end
25 | end
--------------------------------------------------------------------------------
/Support/app/views/log/_log_entry.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | <% expanded_detail_dom_id = "detail_#{branch_name}_#{log_entry[:rev]}" %>
4 |
+
5 |
6 | <%= short_rev(log_entry[:rev]) %>
7 | committed by
8 | <%= log_entry[:author] %>
9 |
10 |
11 |
12 |
13 | <%= htmlize(relative_date(log_entry[:date])) %> ago
14 |
15 |
16 |
17 |
18 |
19 |
20 | <%= htmlize(log_entry[:msg])%>
21 |
22 |
23 | <%= content_tag :div, :class => "diff", :style => "display: none;", :rev => log_entry[:rev], :path => path, :git_path => git.path, :id => expanded_detail_dom_id %>
24 |
25 |
--------------------------------------------------------------------------------
/Commands/Use GitX.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
10 | dispatch(:controller => "misc", :action => "gitx")
11 |
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Visualize History with GitX
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | text
22 | outputLocation
23 | discard
24 | scope
25 | attr.scm.git
26 | semanticClass
27 | action.scm.other
28 | uuid
29 | 1C12DE42-78A9-4DCA-BB55-2B8E6328C72D
30 | version
31 | 2
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Support/spec/controllers/annotate_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 | describe AnnotateController do
3 | include SpecHelpers
4 |
5 | before(:each) do
6 | Git.reset_mock!
7 | end
8 |
9 | describe "when annotating" do
10 | before(:all) do
11 | ENV["TM_SELECTION"] = "1"
12 | Git.command_response["blame", "--abbrev=7", "file.rb"] = fixture_file("blame.txt")
13 | Git.command_response["log", "--date=default", "--format=medium", "--follow", "--name-only", "file.rb"] = fixture_file("log_with_diffs.txt")
14 | @output = capture_output do
15 | dispatch(:controller => "annotate", :file_path => "file.rb")
16 | end
17 | @h = Hpricot(@output)
18 | @log_options = (@h / "select[@name='rev'] / option")
19 | end
20 |
21 | it "should output the log" do
22 | @log_options.first.inner_text.should == "current"
23 | @log_options.length.should == 3
24 | end
25 |
26 | it "should output the annotation" do
27 | @output.should include("Author: Tim Harper")
28 | end
29 | end
30 | end
--------------------------------------------------------------------------------
/Commands/Start Gitk.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
10 | dispatch(:controller => "misc", :action => "gitk")
11 |
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Visualize Branch History With GitK
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | text
22 | outputLocation
23 | discard
24 | scope
25 | attr.scm.git
26 | semanticClass
27 | action.scm.other
28 | uuid
29 | 20F5C491-F71C-4963-9C61-DF7294976550
30 | version
31 | 2
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Support/app/views/annotate/_navigate_box.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Commands : <%= %w[next previous open branch tag].map { |word| "(#{word[0..0]}) #{word[1..-1]}" } * ' / ' %>
5 |
6 | Annotations for ‘<%= htmlize(shorten(@file_path)) %>’ on branch ‘<%= git.branch.current_name %>’
7 |
8 |
9 | <%=
10 | formatted_options = [["current", ""]] + @log_entries.map do |le|
11 | unless le[:msg].nil?
12 | msg = le[:msg].split("\n").first
13 | else
14 | msg = ''
15 | end
16 |
17 | le_str = [short_rev(le[:rev]), relative_date(le[:date]), le[:author], msg].compact.join(' - ')
18 | [le_str, short_rev(le[:rev]), le[:filepath]]
19 | end
20 |
21 | select_box( "rev",
22 | options_for_select(formatted_options, revision),
23 | :onchange => "show_annotation($F(this))"
24 | ) %>
25 |
26 |
--------------------------------------------------------------------------------
/Commands/Use Gitnub.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
10 | dispatch(:controller => "misc", :action => "gitnub")
11 |
12 | input
13 | selection
14 | inputFormat
15 | text
16 | name
17 | Visualize History with Gitnub
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | text
22 | outputLocation
23 | discard
24 | scope
25 | attr.scm.git
26 | semanticClass
27 | action.scm.other
28 | uuid
29 | 1FF5FF82-13A0-4C83-BAD6-D67AE8180FA9
30 | version
31 | 2
32 |
33 |
34 |
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2008 Tim Harper
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/Support/resource/toggle.js:
--------------------------------------------------------------------------------
1 | function set_togglable_visibility(dom_id, state) {
2 | link = $("toggle_link_" + dom_id);
3 | detail_div = $(dom_id)
4 | if (state) {
5 | link.update("-");
6 | detail_div.show();
7 | }
8 | else
9 | {
10 | link.update("+");
11 | detail_div.hide()
12 | }
13 | }
14 |
15 | function toggle_diff(dom_id) {
16 | e = $(dom_id)
17 | if (! e.readAttribute("loaded")) {
18 | e.update(dispatch({controller: 'diff', action: 'diff', revision: e.readAttribute("rev"), git_path: e.readAttribute("git_path"), path: (e.readAttribute("path") || ""), layout: false}))
19 | e.setAttribute("loaded", "");
20 | }
21 |
22 | set_togglable_visibility( dom_id, ! e.visible() );
23 | }
24 |
25 | function toggle_log(dom_id) {
26 | e = $(dom_id)
27 | if (! e.readAttribute("loaded")) {
28 | e.update(dispatch({controller: 'log', action: 'log', revisions: e.readAttribute("revisions"), git_path: e.readAttribute("git_path"), path: (e.readAttribute("path") || ""), layout: false}))
29 | // e.setAttribute("loaded");
30 | }
31 |
32 | set_togglable_visibility( dom_id, ! e.visible() );
33 | }
34 |
--------------------------------------------------------------------------------
/Macros/Next Rebase Command.tmMacro:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | commands
6 |
7 |
8 | argument
9 |
10 | action
11 | findNext
12 | findInProjectIgnoreCase
13 |
14 | findString
15 | ^\s*(pick|p|reword|r|edit|e|squash|s|fixup|f)
16 | ignoreCase
17 |
18 | regularExpression
19 |
20 | replaceAllScope
21 | document
22 | wrapAround
23 |
24 |
25 | command
26 | findWithOptions:
27 |
28 |
29 | keyEquivalent
30 | ^n
31 | name
32 | Next Rebase Command
33 | scope
34 | text.git-rebase
35 | uuid
36 | 683BF855-9BC9-47A6-89DD-7C2192E62FD7
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Support/lib/commands/stash.rb:
--------------------------------------------------------------------------------
1 | require ENV['TM_SUPPORT_PATH'] + '/lib/ui.rb'
2 |
3 | class SCM::Git::Stash < SCM::Git::CommandProxyBase
4 | def list
5 | base.command("stash", "list").split("\n").map do |line|
6 | /^(.+?):(.+)$/.match(line)
7 | name = $1
8 | description = $2
9 | /([0-9]+)/.match(name)
10 | {:id => $1.to_i, :name => name, :description => description}
11 | end
12 | end
13 |
14 | def save(desciption = "")
15 | params = []
16 | params << desciption unless desciption.nil? || desciption.empty?
17 | base.command("stash", "save", *params)
18 | end
19 |
20 | def diff(name)
21 | base.parse_diff(base.command("stash", "show", "-p", name))
22 | end
23 |
24 | def apply(name)
25 | args = ["stash", "apply"]
26 | args << "--index" if options[:index]
27 | args << name
28 | base.command(*args)
29 | end
30 |
31 | def pop(name, options = {})
32 | args = ["stash", "pop"]
33 | args << "--index" if options[:index]
34 | args << name
35 | base.command(*args)
36 | end
37 |
38 | def clear
39 | base.command("stash", "clear")
40 | end
41 | end
--------------------------------------------------------------------------------
/Support/app/views/diff/_diff_check_result.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | <%= link_to_relative_file(git, diff_result[:file_path], diff_result[:file_line]) %>
6 |
7 |
8 |
9 | <% diff_result[:lines].each do |line|
10 | next if @diff_line_count >= Git::DEFAULT_DIFF_LIMIT
11 | @diff_line_count += 1
12 | line_num_class, row_class = case line[:type]
13 | when :deletion then ["", "del"]
14 | when :insertion then ["", "ins"]
15 | when :eof then ["line-num-eof", "eof"]
16 | when :cut then ["line-num-cut", "cut-line"]
17 | else
18 | ["", "unchanged"]
19 | end
20 | %>
21 |
22 |
23 | <%= htmlize(diff_result[:warning]) %>
24 |
25 |
26 | <%= diff_result[:file_line] %>
27 | <%= htmlize(line[:text]) %>
28 |
29 | <% end %>
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Support/app/controllers/annotate_controller.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | class AnnotateController < ApplicationController
4 | include DateHelpers
5 | include AnnotateHelper
6 | layout "application", :except => "update"
7 | def index
8 | @file_path = params[:file_path] || ENV['TM_FILEPATH']
9 | @annotations = git.annotate(@file_path)
10 |
11 | if @annotations.nil?
12 | puts "Error. Aborting"
13 | abort
14 | end
15 |
16 | @log_entries = git.log(:path => @file_path, :follow => true, :name => true)
17 | render "index"
18 | end
19 |
20 | def update
21 | file_path = params[:filepath] || ENV['TM_FILEPATH']
22 | revision = params[:revision]
23 |
24 | @annotations = git.annotate(file_path, revision)
25 |
26 | if @annotations.nil?
27 | puts "Error. Aborting"
28 | abort
29 | end
30 |
31 | # f = Formatters::Annotate.new(:selected_revision => revision, :as_partial => true)
32 | # f.header "Annotations for ‘#{htmlize(shorten(file_path))}’"
33 | # f.content annotations
34 | render "_content", :locals => { :annotations => @annotations, :revision => revision }
35 | render "_select_revision", :locals => { :revision => revision}
36 | end
37 | end
--------------------------------------------------------------------------------
/Support/app/views/diff/_submodule_diff_result.html.erb:
--------------------------------------------------------------------------------
1 | <%
2 | case diff_result[:status]
3 | when :new
4 | %>
5 | Submodule added: <%= link_to_relative_file(git, diff_result[:right][:file_path]) %>
6 | <%
7 | when :deleted
8 | %>
9 | Submodule deleted: <%= link_to_relative_file(git, diff_result[:left][:file_path]) %>
10 | <%
11 | when :modified
12 | file_path = diff_result[:left][:file_path]
13 | revision_left, revision_right = extract_submodule_revisions(diff_result)
14 |
15 | revision_right = diff_result[:lines][1][:text].gsub("Subproject commit ", "")
16 | %>
17 | Submodule modified: <%= link_to_relative_file(git, diff_result[:left][:file_path]) %>
18 | <%
19 | revisions = [git.short_rev(revision_left), git.short_rev(revision_right)] * ".."
20 | expanded_detail_dom_id = "log_" + revisions.gsub(".", "_")
21 | %>
22 | +
23 | <%= revisions %>
24 | <%= content_tag :div, :class => "log", :style => "display: none;", :revisions => revisions, :git_path => git.path_for(file_path), :id => expanded_detail_dom_id %>
25 |
26 | <%
27 | end
28 | %>
--------------------------------------------------------------------------------
/Support/app/controllers/status_controller.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require LIB_ROOT + '/ui.rb'
3 |
4 | class StatusController < ApplicationController
5 | layout "application", :except => [:edit_conflicted_file]
6 |
7 | include SubmoduleHelper
8 | def index
9 | file_or_path = *(params[:path] || git.paths.first)
10 | puts 'Status for ' + file_or_path.map { |e| "‘#{htmlize(shorten(e))}’" }.join(', ') + " on branch ‘#{git.branch.current_name}’ "
11 | status_data = git.status(file_or_path)
12 | render "_status", :locals => {:status_data => status_data}
13 |
14 | git.submodule.all(:path => file_or_path).each do |submodule|
15 | next if (status_data = submodule.git.status).blank?
16 | render_submodule_header(submodule)
17 | render "_status", :locals => {:status_data => status_data, :git => submodule.git}
18 | end
19 | end
20 |
21 | def edit_conflicted_file
22 | file_or_path = git.path
23 | conflicts = git.status(file_or_path).select { |file_status| file_status[:status][:short] == "C" }
24 | if conflicts.empty?
25 | puts "No conflicted files"
26 | exit_show_tool_tip
27 | end
28 | index = TextMate::UI.menu(conflicts.map { |conflict| conflict[:display] })
29 | tm_open(conflicts[index][:path]) if index
30 | exit_discard
31 | end
32 | end
--------------------------------------------------------------------------------
/Support/spec/fixtures/log.txt:
--------------------------------------------------------------------------------
1 | commit 2762e1264c439dced7f05eacd33fc56499b8b779
2 | Author: Tim Harper
3 | Date: Mon Feb 4 07:51:25 2008 -0700
4 |
5 | bugfix - diff was not parsing the index line sometimes because it varies on deleted files
6 |
7 | made more failproof
8 |
9 | commit d31fffa9df961f057019d9845c5984a264d3d574
10 | Author: Tim Harper
11 | Date: Mon Feb 4 07:44:08 2008 -0700
12 |
13 | diff-rendering of if there is a new-line at the end of a file or not.
14 |
15 | commit bd481e454a9639e8fe554aacdff91154709e11cd
16 | Author: Tim Harper
17 | Date: Mon Feb 4 07:31:18 2008 -0700
18 |
19 | Diff mode:
20 | now with "cut" visuals, links to files. Compare branches now uses the sexy diff mode.
21 |
22 | commit 198fc930b5b1aaa93ba29a9535a768b5c120ea49
23 | Author: Tim Harper
24 | Date: Mon Feb 4 06:45:47 2008 -0700
25 |
26 | new style for diff implemented. diff returns parsed data, which is then passed to the formatter.
27 |
28 | commit 2aedd4e30f077a6712ede1f1bd328e812839913f
29 | Author: Tim Harper
30 | Date: Mon Feb 4 04:51:39 2008 -0700
31 |
32 | Broke out diff command into it's own class, and seperated the view code into a new Formatters::Diff object
33 |
34 |
--------------------------------------------------------------------------------
/Commands/SVN Fetch.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "svn", :action => "fetch"
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | SVN Fetch
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | uuid
40 | 1CCC4394-A243-4E78-A720-B2DA1BC37DC0
41 | version
42 | 2
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Commands/SVN Rebase.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "svn", :action => "rebase"
12 | input
13 | selection
14 | inputFormat
15 | text
16 | name
17 | SVN Rebase
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | uuid
40 | CFB9BB9D-4F47-47DA-819B-58F0B29FA560
41 | version
42 | 2
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Commands/SVN Dcommit.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "svn", :action => "dcommit"
12 | input
13 | selection
14 | inputFormat
15 | text
16 | name
17 | SVN Dcommit
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | uuid
40 | 8FD8CC00-0A38-4472-9C3A-F22AE289B3A9
41 | version
42 | 2
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Support/lib/commands/remote.rb:
--------------------------------------------------------------------------------
1 | class SCM::Git::Remote < SCM::Git::CommandProxyBase
2 | def [](name)
3 | @remotes ||= {}
4 | @remotes[name] ||= SCM::Git::Remote::RemoteProxy.new(@base, self, name)
5 | end
6 |
7 | def all
8 | names.map do |name|
9 | RemoteProxy.new(self, @base, name)
10 | end
11 | end
12 |
13 | def names
14 | @base.command("remote").split("\n")
15 | end
16 |
17 | class RemoteProxy
18 | attr_reader :name
19 |
20 | def initialize(base, parent, name, options = {})
21 | @base = base
22 | @parent = parent
23 | @name = name
24 | end
25 |
26 | def fetch_refspec(reload = false)
27 | @fetch_refspec = nil if reload
28 | @fetch_refspec ||= @base.config["remote.#{name}.fetch"]
29 | end
30 |
31 | def remote_branch_name_for(branch_name, format = :short)
32 | branch_name = "refs/heads/#{branch_name}" unless branch_name[0..10] == "refs/heads/"
33 | sub_from, sub_to = fetch_refspec.scan(/\+?(.+)\*:(.+)\*$/).flatten
34 | branch_name = branch_name.gsub(sub_from, sub_to)
35 | if format == :short
36 | branch_name.gsub("refs/remotes/", "")
37 | else
38 | branch_name
39 | end
40 | end
41 |
42 | def remote_branch_prefix
43 | /\*:(.+)\*/.match(fetch_refspec)
44 | $1
45 | end
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/Support/lib/commands/config.rb:
--------------------------------------------------------------------------------
1 | class SCM::Git::Config < SCM::Git::CommandProxyBase
2 | DEFAULT_LOG_LIMIT = 100
3 | def [](*params)
4 | scope, key = process_keys(params)
5 | r = base.command(*(["config"] + config_args(scope) + [key]))
6 | r.blank? ? nil : r.gsub(/\n$/, '')
7 | end
8 |
9 | def []=(*params)
10 | value = params.pop
11 | scope, key = process_keys(params)
12 | args = ["config"] + config_args(scope)
13 | if value
14 | args += [key, value]
15 | else
16 | args += ["--unset", key]
17 | end
18 | base.command(*args)
19 | end
20 |
21 | def log_limit
22 | self["git-tmbundle.log.limit"] || DEFAULT_LOG_LIMIT
23 | end
24 |
25 | def show_diff_check?
26 | %w[yes 1 auto].include?(self["git-tmbundle.show-diff-check"].to_s.downcase.strip)
27 | end
28 |
29 | def context_lines
30 | self["git-tmbundle.log.context-lines"]
31 | end
32 |
33 | protected
34 | def config_args(scope)
35 | case scope.to_s
36 | when "global"
37 | ["--global"]
38 | when "local", "file"
39 | ["--file", File.join(@base.path, ".git/config")]
40 | when "default"
41 | []
42 | else
43 | raise "I don't understand the scope #{scope.inspect}"
44 | end
45 | end
46 |
47 | def process_keys(params)
48 | params = [:default, params.first] if params.length == 1
49 | params
50 | end
51 | end
--------------------------------------------------------------------------------
/Commands/Commit.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch(:controller => "commit")
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Commit…
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.commit
43 | uuid
44 | 55CCBE51-3C13-46D8-92D9-52EAD7A5D2D6
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Status.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
10 | dispatch(:controller => "status")
11 |
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Status
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.status
43 | uuid
44 | 41F8764A-63DE-4965-9192-918E49E15907
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Show Log.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "log", :action => "index"
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Log
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.log
43 | uuid
44 | 46662F92-7739-42A7-B7CD-0527A0474BDC
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Pull.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "remote", :action => "pull"
12 | input
13 | selection
14 | inputFormat
15 | text
16 | name
17 | Pull
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.pull
43 | uuid
44 | 6494E41A-04CE-4D30-BD9A-B50056A7C13F
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Create Tag.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "tag", :action => "create"
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Create Tag…
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.tag
43 | uuid
44 | C6CD5A2A-E1DA-4D94-B561-331A2366AAC8
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Fetch.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "remote", :action => "fetch"
12 | input
13 | selection
14 | inputFormat
15 | text
16 | name
17 | Fetch
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.fetch
43 | uuid
44 | 491D8DB3-8CB2-4888-ACD8-C94FAB125B38
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Stash.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
10 | dispatch :controller => "stash", :action => "save"
11 |
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Stash
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.other.stash
43 | uuid
44 | 917D405B-0488-4FDE-966A-54E1F922FCBD
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Git Init.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "misc", :action => "init"
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Initialize Repository
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | -attr.scm
41 | semanticClass
42 | action.scm.new
43 | uuid
44 | 556EF65D-C59B-4A15-BA4A-D5D87C2695A0
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Merge.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => 'branch', :action => 'merge'
12 | input
13 | selection
14 | inputFormat
15 | text
16 | name
17 | Merge…
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.branches
43 | uuid
44 | 246BC5D6-F4DC-458B-8966-C601B65AA1E9
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Outgoing.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "log", :action => "outgoing"
12 | input
13 | selection
14 | inputFormat
15 | text
16 | name
17 | Outgoing
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.other
43 | uuid
44 | 1D25F132-718E-4B97-95CC-724AAC35E46C
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Clear Stash.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
10 | dispatch :controller => "stash", :action => "clear"
11 |
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Clear Stash…
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | text
22 | outputLocation
23 | toolTip
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.other.stash
43 | uuid
44 | 6AA96188-1428-4E09-94D8-755107CFC48E
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Push.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "remote", :action => "push"
12 | input
13 | selection
14 | inputFormat
15 | text
16 | name
17 | Push Current Branch
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.push
43 | uuid
44 | 3F84F9EB-027A-4200-B29B-C99EFA09F453
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Show Stash.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
10 | dispatch :controller => "stash", :action => "show"
11 |
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Show Stash
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.other.stash
43 | uuid
44 | 5E37F050-85A0-4CAE-91D1-DC50E2F65024
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Submodules.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "submodule", :action => "index"
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Submodules…
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.other
43 | uuid
44 | 3F77F0FC-F476-4B83-92D1-77D854A9D64D
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Add files to the index.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "commit", :action => "add"
12 | input
13 | selection
14 | inputFormat
15 | text
16 | name
17 | Add to Index
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | text
22 | outputLocation
23 | toolTip
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.add
43 | uuid
44 | E0901B2E-8953-4A2F-A872-8DBE1A047370
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Config.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "config", :action => "index"
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Config…
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | -attr.scm, attr.scm.git
41 | semanticClass
42 | action.scm.preferences
43 | uuid
44 | 794C7EF9-B0A5-4B27-90BD-000837237B85
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Create Branch.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
10 | dispatch(:controller => "branch", :action => "create")
11 |
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Create Branch…
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | text
22 | outputLocation
23 | toolTip
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.branches
43 | uuid
44 | FF012371-E6C2-4D97-BCD2-9B6237C9BF5B
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Delete Branch.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch(:controller => "branch", :action => "delete")
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Delete Branch...
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | text
22 | outputLocation
23 | toolTip
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.branches
43 | uuid
44 | 508C7FCD-E5DD-4E60-88C3-A668C48273B7
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Amend Last Commit.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch(:controller => "commit", :type => "amend")
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Amend Last Commit…
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.amend
43 | uuid
44 | 2F24C9CB-23D0-4FDA-9C8D-210027DCEB27
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Browse Annotated File (blame).tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch(:controller => "annotate")
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Browse Annotated File (Blame)
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.blame
43 | uuid
44 | B3577B4D-A3F1-4CB4-94B0-7A87CA658664
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Pop Stash.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "stash", :action => "pop"
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Pop Stash (Apply then drop)
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.other.stash
43 | uuid
44 | 47EB2C81-B093-4627-9DE7-454A60C3A98C
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Switch to Branch.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
10 | dispatch(:controller => "branch", :action => "switch")
11 |
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Branches (Show/Switch)…
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | text
22 | outputLocation
23 | toolTip
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.branches
43 | uuid
44 | 7F8D2058-E106-40DC-9FBE-F32A1202D158
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Compare Revisions.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "diff", :action => "compare_revisions"
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Compare Revisions…
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.diff
43 | uuid
44 | E9180CC9-BA7D-4271-A0A4-0263D8A71F46
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Edit Conflicted File.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "status", :action => "edit_conflicted_file"
12 | input
13 | selection
14 | inputFormat
15 | text
16 | name
17 | Edit Conflicted File…
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | text
22 | outputLocation
23 | toolTip
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.conflicts
43 | uuid
44 | 0DBC221A-B726-4367-A5E1-04AB999F8CC2
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Commands/Show Uncommitted Changes.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | dispatch :controller => "diff", :action => "uncommitted_changes"
12 | input
13 | none
14 | inputFormat
15 | text
16 | name
17 | Show Uncommitted Changes
18 | outputCaret
19 | afterOutput
20 | outputFormat
21 | html
22 | outputLocation
23 | newWindow
24 | requiredCommands
25 |
26 |
27 | command
28 | git
29 | locations
30 |
31 | /usr/local/git/bin/git
32 | /opt/local/bin/git
33 | /usr/local/bin/git
34 |
35 | variable
36 | TM_GIT
37 |
38 |
39 | scope
40 | attr.scm.git
41 | semanticClass
42 | action.scm.status
43 | uuid
44 | 37CC38F5-AF4C-4915-B925-1DC810C25C8A
45 | version
46 | 2
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Support/spec/lib/commands/log_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../spec_helper'
2 |
3 | describe Git do
4 | before(:each) do
5 | @git = Git.new
6 | end
7 | include SpecHelpers
8 |
9 | describe "when parsing a plain log" do
10 | before(:each) do
11 | @entries = @git.parse_log( fixture_file('log.txt'))
12 | end
13 |
14 | it "should parse out all items" do
15 | @entries.should have(5).entries
16 | end
17 |
18 | it "should parse out the author, msg, and revision" do
19 | result = @entries.first
20 | result[:rev].should == "2762e1264c439dced7f05eacd33fc56499b8b779"
21 | result[:author].should == "Tim Harper "
22 | result[:date].should == Time.parse("Mon Feb 4 07:51:25 2008 -0700")
23 | result[:msg].should == %Q{bugfix - diff was not parsing the index line sometimes because it varies on deleted files
24 |
25 | made more failproof}
26 | end
27 | end
28 |
29 | describe "when parsing a log with diffs" do
30 | before(:each) do
31 | @entries = @git.parse_log( fixture_file("log_with_diffs.txt"))
32 | @entry = @entries.first
33 | end
34 |
35 | it "should extract and parse diffs" do
36 | @entry[:diff].should_not be_nil
37 | @entry_diff = @entry[:diff].first
38 | @entry_diff[:left][:file_path].should == "Commands/Browse Annotated File (blame).tmCommand"
39 | @entry_diff[:right][:file_path].should == "Commands/Browse Annotated File (blame).tmCommand"
40 | @entry_diff[:lines].length.should == 19
41 | end
42 | end
43 |
44 | end
45 |
--------------------------------------------------------------------------------
/Support/spec/lib/commands/annotate_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../spec_helper'
2 |
3 | describe SCM::Git do
4 | before(:each) do
5 | @annotate = Git.new
6 | end
7 | include SpecHelpers
8 |
9 | describe "when parsing a annotate" do
10 | before(:each) do
11 | @lines = @annotate.parse_annotation(File.read("#{FIXTURES_DIR}/annotate.txt"))
12 | end
13 |
14 | it "should parse out all items" do
15 | @lines.should have(428).entries
16 | end
17 |
18 | it "should parse out the author, msg, and revision" do
19 | line = @lines.first
20 | line[:rev].should == "26e2d189"
21 | line[:filepath].should be_nil
22 | line[:author].should == "Tim Harper"
23 | line[:date].should == Time.parse("2008-03-02 00:24:40 -0700")
24 | line[:text].should == 'require LIB_ROOT + "/parsers.rb"'
25 | end
26 | end
27 |
28 | describe "when parsing a annotate with a RENAMED file" do
29 | before(:each) do
30 | @lines = @annotate.parse_annotation(File.read("#{FIXTURES_DIR}/annotate_renamed.txt"))
31 | end
32 |
33 | it "should parse out all items" do
34 | @lines.should have(428).entries
35 | end
36 |
37 | it "should parse out the author, msg, and revision" do
38 | line = @lines.first
39 | line[:rev].should == "26e2d189"
40 | line[:filepath].should == "Support/lib/git.rb"
41 | line[:author].should == "Tim Harper"
42 | line[:date].should == Time.parse("2008-03-02 00:24:40 -0700")
43 | line[:text].should == 'require LIB_ROOT + "/parsers.rb"'
44 | end
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/Support/spec/lib/git_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 |
3 | describe SCM::Git do
4 | before(:each) do
5 | @git = SCM::Git.new
6 | Git.reset_mock!
7 | end
8 |
9 | it "should describe a revision, defaulting to use all refs" do
10 | Git.command_response["describe", "--all", "1234"] = "tag-1234\n"
11 | `ls` # set the exit status code to 0
12 | @git.describe("1234").should == "tag-1234"
13 | end
14 |
15 | it "should return the current revision" do
16 | Git.command_response["rev-parse", "HEAD"] = "1234\n"
17 | @git.current_revision.should == "1234"
18 | end
19 |
20 | it "should auto_add_rm files depending on their existence" do
21 | File.stub!(:exist?).with("/base/existing_file.txt").and_return(true)
22 | File.stub!(:exist?).with("/base/deleted_file.txt").and_return(false)
23 | @git.should_receive(:add).with(["existing_file.txt"]).and_return("")
24 | @git.should_receive(:rm).with(["deleted_file.txt"]).and_return("")
25 | @git.auto_add_rm(["existing_file.txt", "deleted_file.txt"])
26 | end
27 |
28 | describe "using submodule git relative paths" do
29 | before(:each) do
30 | @sub_git = Git.new(:parent => @git, :path => File.join(@git.path, "subproject"));
31 | end
32 |
33 | it "should return absolute paths" do
34 | @sub_git.path_for("file.txt").should == File.join(@git.path, "subproject/file.txt")
35 | end
36 |
37 | it "should return a relative path from the root git" do
38 | @sub_git.root_relative_path_for("file.txt").should == "subproject/file.txt"
39 | end
40 | end
41 | it
42 |
43 | end
44 |
--------------------------------------------------------------------------------
/Commands/Fixup!.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18 -wKU
9 |
10 | def escape(choice)
11 | choice.gsub(/[,|\\$]/, '\\\\\0')
12 | end
13 |
14 | choices = %x{ cd "$TM_PROJECT_DIRECTORY" && "${TM_GIT:-git}" log --pretty=tformat:'%s' -n15 }.split(/\n/)
15 | choices.reject! { |choice| choice =~ /^(fixup|squash)\b/ }
16 | choices.map! { |choice| escape choice }
17 |
18 | STDOUT << "fixup! ${1|#{choices.join ','}|}"
19 |
20 | input
21 | none
22 | inputFormat
23 | text
24 | name
25 | Fixup!
26 | outputCaret
27 | afterOutput
28 | outputFormat
29 | snippet
30 | outputLocation
31 | atCaret
32 | requiredCommands
33 |
34 |
35 | command
36 | git
37 | locations
38 |
39 | /usr/local/git/bin/git
40 | /opt/local/bin/git
41 | /usr/local/bin/git
42 |
43 | variable
44 | TM_GIT
45 |
46 |
47 | scope
48 | text.git-commit
49 | tabTrigger
50 | fix
51 | uuid
52 | 11CB0218-E38D-4ACE-9504-77BB3A224C15
53 | version
54 | 2
55 |
56 |
57 |
--------------------------------------------------------------------------------
/Support/spec/lib/commands/remote_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../spec_helper'
2 |
3 | describe SCM::Git::Remote do
4 | before(:each) do
5 | @git = Git.new
6 | Git.reset_mock!
7 | end
8 |
9 | include SpecHelpers
10 |
11 | it "should return a list of remote names" do
12 | Git.command_response["remote"] = "github\norigin"
13 | @git.remote.names.should == ["github", "origin"]
14 | end
15 |
16 | it "should return an Array of RemoteProxy objects" do
17 | Git.command_response["remote"] = "origin"
18 | remotes = @git.remote.all
19 | remotes.should have(1).item
20 | remotes.first.should be_kind_of(Git::Remote::RemoteProxy)
21 | remotes.first.name.should == "origin"
22 | end
23 |
24 | it "should retrieve a fetch refspec" do
25 | refspec = "+refs/heads/*:refs/remotes/origin/*"
26 | @git.config.should_receive(:[]).with("remote.origin.fetch").and_return("+refs/heads/*:refs/remotes/origin/*")
27 | @git.remote["origin"].fetch_refspec.should == refspec
28 | end
29 |
30 | it "should find the local name for a refspec" do
31 | remote = @git.remote["origin"]
32 | remote.stub!(:fetch_refspec).and_return("+refs/heads/*:refs/remotes/origin/*")
33 | remote.remote_branch_name_for("refs/heads/master").should == "origin/master"
34 | remote.remote_branch_name_for("master").should == "origin/master"
35 | remote.remote_branch_name_for("refs/heads/master", :full).should == "refs/remotes/origin/master"
36 | end
37 |
38 | it "should find the remote refspec prefix" do
39 | remote = @git.remote["origin"]
40 | remote.stub!(:fetch_refspec).and_return("+refs/heads/*:refs/remotes/origin/*")
41 | remote.remote_branch_prefix.should == "refs/remotes/origin/"
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/Support/app/views/config/index.html.erb:
--------------------------------------------------------------------------------
1 | Git Config
2 | Values are saved when the form-field loses focus.
3 |
45 |
46 |
--------------------------------------------------------------------------------
/Support/spec/fixtures/changed_files.diff:
--------------------------------------------------------------------------------
1 | diff --git a/Support/lib/commands/diff.rb b/Support/lib/commands/diff.rb
2 | index 2e44996..3820608 100644
3 | --- a/Support/lib/commands/diff.rb
4 | +++ b/Support/lib/commands/diff.rb
5 | @@ -5,6 +5,25 @@ class SCM::Git::Diff
6 | base = File.expand_path("..", git_dir(file)) if base.nil?
7 | Dir.chdir(base)
8 | file = '.' if file == base
9 | - command("diff", file.sub(/^#{Regexp.escape base}\//, ''))
10 | + parse_diff(command("diff", file.sub(/^#{Regexp.escape base}\//, '')))
11 | + end
12 | +
13 | + def parse_diff(output)
14 | + output.split("\n").each do |line|
15 | + css_class = case line
16 | + when /^(diff |index |@@|\+\+\+|\-\-\-)/
17 | + "info"
18 | + when /^\+/
19 | + "addition"
20 | + when /^\-/
21 | + "deletion"
22 | + when /^diff /
23 | + "diff_cmd"
24 | + else
25 | + ""
26 | + end
27 | + puts "#{htmlize(line)}
"
28 | + end
29 | +
30 | end
31 | end
32 | \ No newline at end of file
33 | diff --git a/Support/lib/formatters/diff.rb b/Support/lib/formatters/diff.rb
34 | index b0faae6..2ac2101 100644
35 | --- a/Support/lib/formatters/diff.rb
36 | +++ b/Support/lib/formatters/diff.rb
37 | @@ -30,21 +30,6 @@ class Formatters::Diff
38 |
39 | def content(diff_result)
40 | puts ''
41 | - diff_result.split("\n").each do |line|
42 | - css_class = case line
43 | - when /^(diff |index |@@|\+\+\+|\-\-\-)/
44 | - "info"
45 | - when /^\+/
46 | - "addition"
47 | - when /^\-/
48 | - "deletion"
49 | - when /^diff /
50 | - "diff_cmd"
51 | - else
52 | - ""
53 | - end
54 | - puts "#{htmlize(line)}
"
55 | - end
56 |
57 | puts ''
58 | end
--------------------------------------------------------------------------------
/Support/app/controllers/submodule_controller.rb:
--------------------------------------------------------------------------------
1 | require LIB_ROOT + '/ui.rb'
2 |
3 | class SubmoduleController < ApplicationController
4 | def index
5 | render "index"
6 | end
7 |
8 | def list
9 | @submodules = git.submodule.all
10 | render "list"
11 | end
12 |
13 | def add
14 | (repository_path = prompt_repository_path) &&
15 | (parent_folder = prompt_parent_folder) &&
16 | (module_name = prompt_module_name(repository_path)) ||
17 | (cancel and return)
18 |
19 | # This is messy, but I'm not entirely sure what is going to happen with this yet (there may be some parsing going on that will require interaction between the view and the controller)
20 | puts ""
21 | stream = git.submodule.add(repository_path, File.join(parent_folder, module_name))
22 | stream.pipe_to(STDOUT)
23 | puts " "
24 |
25 | puts htmlize(git.submodule.init_and_update)
26 |
27 | puts <<-EOF
28 | Done.
29 | EOF
30 | end
31 |
32 | def update
33 | puts ""
34 | puts git.submodule.init_and_update
35 | puts " "
36 | end
37 |
38 | #
39 | ##
40 | ###
41 | protected
42 | def prompt_repository_path
43 | TextMate::UI.request_string(:title => "Add submodule", :prompt => "Enter the submodule clone URL")
44 | end
45 |
46 | def prompt_parent_folder
47 | TextMate::UI.request_directory("Select the parent folder for the submodule:", :initial_directory => git.path)
48 | end
49 |
50 | def prompt_module_name(repository_path = "")
51 | /([^\/]+?)(.git){0,1}$/.match(repository_path)
52 | module_name = TextMate::UI.request_string(:title => "What do you want to call the module (will be the folder name)?", :default => $1 )
53 | end
54 |
55 | def cancel
56 | puts "Canceled"
57 | true
58 | end
59 | end
--------------------------------------------------------------------------------
/Support/tmvc/spec/spec_helpers.rb:
--------------------------------------------------------------------------------
1 | module SpecHelpers
2 | PUTS_CAPTURE_CLASSES = []
3 | def fixture_file(filename)
4 | File.read("#{FIXTURES_DIR}/#{filename}")
5 | end
6 |
7 | def set_constant_forced(klass, constant_name, constant)
8 | klass.class_eval do
9 | remove_const(constant_name) if const_defined?(constant_name)
10 | const_set(constant_name, constant)
11 | end
12 | end
13 |
14 | def capture_output(&block)
15 | old_stdout = Object::STDOUT
16 | io_stream = StringIO.new
17 | begin
18 | set_constant_forced(Object, "STDOUT", io_stream)
19 | PUTS_CAPTURE_CLASSES.each do |klass|
20 | klass.class_eval do
21 | def puts(*args)
22 | args.each{ |arg| Object::STDOUT.puts arg}
23 | end
24 | end
25 | end
26 | yield
27 | ensure
28 | set_constant_forced(Object, "STDOUT", old_stdout)
29 | end
30 | io_stream.rewind
31 | io_stream.read
32 | end
33 |
34 |
35 | def branch_stub(options = {})
36 | branch = stub("branch", options)
37 | [:name, :tracking_branch_name].each do |key|
38 | next unless options[key]
39 | branch.stub!(key).with(:long).and_return(options[key])
40 | branch.stub!(key).with().and_return(options[key].gsub(/refs\/(heads|remotes)\//, ""))
41 | end
42 | if options.has_key?(:remote)
43 | branch.stub!(:remote).and_return(stub("remote", :name => options[:remote]))
44 | branch.stub!(:remote_name).and_return(options[:remote])
45 | end
46 | branch
47 | end
48 |
49 | def stub_current_branch(git, options = {})
50 | git.branch.stub!(:current).and_return(branch_stub(options))
51 | git.branch.stub!(:current_name).with(:long).and_return(git.branch.current.name(:long))
52 | git.branch.stub!(:current_name).with().and_return(git.branch.current.name)
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/Support/app/controllers/commit_controller.rb:
--------------------------------------------------------------------------------
1 | require LIB_ROOT + '/partial_commit_worker.rb'
2 | class CommitController < ApplicationController
3 | layout "application", :except => [:add]
4 |
5 | def index
6 | if git.merge_message
7 | @status = git.status
8 | @message = git.merge_message
9 | render "merge_commit"
10 | else
11 | run_partial_commit
12 | end
13 | end
14 |
15 | def merge_commit
16 | message = params[:message]
17 | statuses = git.status(git.path)
18 | files = statuses.map { |status_options| (status_options[:status][:short] == "G") ? git.make_local_path(status_options[:path]) : nil }.compact
19 |
20 | git.auto_add_rm(files)
21 | res = git.commit(message, [])
22 |
23 | render "_commit_result", :locals => { :result => res, :files => files, :message => message }
24 | end
25 |
26 | def add
27 | paths = git.paths(:unique => true, :fallback => :current_file)
28 | git.add(paths)
29 | paths.each { |file| puts "Added '#{git.relative_path_for(file)}' to the index" }
30 | exit_show_tool_tip
31 | end
32 |
33 | protected
34 | def run_partial_commit
35 | puts "#{commit_worker.title}… "
36 | result = commit_worker.run
37 | render "_commit_result", :locals => result if result
38 | rescue PartialCommitWorker::NotOnBranchException
39 | render "not_on_a_branch"
40 | false
41 | rescue PartialCommitWorker::NothingToCommitException
42 | puts(git.clean_directory? ? "Working directory is clean (nothing to commit)" : "No changes to commit within the current scope. (Try selecting the root folder in the project drawer?)")
43 | rescue PartialCommitWorker::NothingToAmendException
44 | puts "Nothing to amend."
45 | rescue PartialCommitWorker::CommitCanceledException
46 | suppress_output
47 | end
48 |
49 | def commit_worker
50 | @commit_worker ||= PartialCommitWorker.factory(params[:type], git)
51 | end
52 | end
--------------------------------------------------------------------------------
/Support/spec/controllers/submodule_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 |
3 | describe SubmoduleController do
4 | include SpecHelpers
5 | include Parsers
6 |
7 | before(:each) do
8 | @git = Git.singleton_new
9 | @controller = SubmoduleController.singleton_new
10 |
11 | @module_repo_path = "git@server:/path/to/my-module.git"
12 | @module_name = "my-module"
13 | end
14 |
15 | # TextMate::UI.should_receive(:request_string).with(
16 | # :title => "Add submodule", :prompt => "Enter the submodule clone URL"
17 | # ).and_return(@module_repo_path)
18 |
19 | # TextMate::UI.should_receive(:request_directory).with(
20 | # "Select the parent folder for the submodule:", :initial_directory => @git.path
21 | # ).and_return("/base/")
22 |
23 | it "should extract an intelligent default" do
24 | TextMate::UI.should_receive(:request_string).with(
25 | :title => "What do you want to call the module (will be the folder name)?", :default => "my-module"
26 | ).and_return(@module_name)
27 | @controller.send(:prompt_module_name, @module_repo_path)
28 | end
29 |
30 | it "should add a repository and output the results of the add / initialize" do
31 | @controller.should_receive(:prompt_repository_path).and_return(@module_repo_path)
32 | @controller.should_receive(:prompt_parent_folder).and_return(@git.path)
33 | @controller.should_receive(:prompt_module_name).and_return(@module_name)
34 |
35 | @git.submodule.should_receive(:add).with(@module_repo_path, File.join("/base/", @module_name)).and_return(StringIO.new("Added!"))
36 | @git.submodule.should_receive(:init_and_update).and_return("Initialized!")
37 |
38 | output = capture_output do
39 | dispatch(:controller => "submodule", :action => "add")
40 | end
41 |
42 | output.should include("Added!")
43 | output.should include("Initialized!")
44 | # puts "#{output} "
45 | end
46 | end
--------------------------------------------------------------------------------
/Support/spec/controllers/diff_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 |
3 | describe DiffController do
4 | include SpecHelpers
5 | include Parsers
6 | before(:each) do
7 | Git.reset_mock!
8 | @git = Git.singleton_new
9 | end
10 |
11 | describe "uncommitted changes" do
12 | before(:each) do
13 | @git.should_receive(:diff).
14 | with(:path => @git.path, :since => "HEAD" ).
15 | and_return(
16 | parse_diff(fixture_file("changed_files.diff"))
17 | )
18 |
19 | @git.submodule.stub!(:all).and_return []
20 |
21 | @output = capture_output do
22 | dispatch(:controller => "diff", :action => "uncommitted_changes")
23 | end
24 | end
25 |
26 | it "should output the diff" do
27 | # puts Git.commands_ran.inspect
28 | # puts @output
29 | @output.should include("Support/lib/formatters/diff.rb")
30 | end
31 |
32 | it "should show a link to open the diff in textmate" do
33 | @output.should include("Open diff in TextMate")
34 | end
35 |
36 | it "should include a javascript include tag for prototype.js" do
37 | @output.should include("prototype.js")
38 | end
39 | end
40 |
41 | describe "diffing submodules" do
42 | before(:each) do
43 | @git.should_receive(:diff).
44 | and_return(
45 | parse_diff(fixture_file("submodules.diff"))
46 | )
47 | @output = capture_output do
48 | dispatch(:controller => "diff", :action => "diff")
49 | end
50 | end
51 |
52 | it "should report the added submodule" do
53 | @output.should include("Submodule added")
54 | end
55 |
56 | it "should report the deleted submodule" do
57 | @output.should include("Submodule deleted")
58 | end
59 |
60 | it "should report the modified submodule" do
61 | @output.should include("Submodule modified")
62 | end
63 | end
64 | end
--------------------------------------------------------------------------------
/Commands/Revert.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 | # encoding: utf-8
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | require ENV['TM_SUPPORT_PATH'] + '/lib/ui.rb'
12 | require ENV['TM_SUPPORT_PATH'] + '/lib/escape.rb'
13 |
14 | git = SCM::Git.new
15 | paths = git.paths(:unique => true, :fallback => :current_file)
16 |
17 | display = paths.map { |e| File.basename(e) }.join("”, “")
18 | plural = (paths.size == 1) ? '' : 's'
19 | files = (paths.size == 1) ? "“#{display}”" : 'files'
20 |
21 | if 'Revert' == TextMate::UI.alert(:warning, "Revert #{files}?", "Do you really want to revert the file#{plural} “#{display}” and lose all local changes?", 'Revert', 'Cancel')
22 |
23 | puts git.revert(paths)
24 |
25 | end
26 |
27 | input
28 | none
29 | inputFormat
30 | text
31 | name
32 | Revert…
33 | outputCaret
34 | afterOutput
35 | outputFormat
36 | text
37 | outputLocation
38 | toolTip
39 | requiredCommands
40 |
41 |
42 | command
43 | git
44 | locations
45 |
46 | /usr/local/git/bin/git
47 | /opt/local/bin/git
48 | /usr/local/bin/git
49 |
50 | variable
51 | TM_GIT
52 |
53 |
54 | scope
55 | attr.scm.git
56 | semanticClass
57 | action.scm.revert
58 | uuid
59 | CDEA521C-8963-414F-8F8E-F9B81EF79ADA
60 | version
61 | 2
62 |
63 |
64 |
--------------------------------------------------------------------------------
/Support/environment.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/tmvc/tmvc.rb'
2 |
3 | LIB_ROOT = ROOT + "/lib"
4 | %w[auto_load date_helpers git].each do |filename|
5 | require "#{LIB_ROOT}/#{filename}.rb"
6 | end
7 | require ENV['TM_SUPPORT_PATH'] + '/lib/escape.rb'
8 | require 'shellwords'
9 | require 'set'
10 |
11 | def shorten(path, base = nil)
12 | return if path.blank?
13 | base = base.gsub(/\/$/, "") if base
14 | project_path =
15 | home_path = ENV['HOME']
16 | case
17 | when base && path =~ /^#{Regexp.escape base}\/(.+)$/
18 | $1
19 | when base && path =~ /^#{Regexp.escape base}\/?$/
20 | "./"
21 | when path == project_path
22 | File.basename(path)
23 | when ENV['TM_PROJECT_DIRECTORY'] && path =~ /^#{Regexp.escape ENV['TM_PROJECT_DIRECTORY']}\/(.+)$/
24 | $1
25 | when ENV['HOME'] && path =~ /^#{Regexp.escape ENV['HOME']}\/(.+)$/
26 | '~/' + $1
27 | else
28 | path
29 | end
30 | end
31 |
32 | class Module
33 | def alias_method_chain(target, feature)
34 | # Strip out punctuation on predicates or bang methods since
35 | # e.g. target?_without_feature is not a valid method name.
36 | aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
37 | yield(aliased_target, punctuation) if block_given?
38 |
39 | with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"
40 |
41 | alias_method without_method, target
42 | alias_method target, with_method
43 |
44 | case
45 | when public_method_defined?(without_method)
46 | public target
47 | when protected_method_defined?(without_method)
48 | protected target
49 | when private_method_defined?(without_method)
50 | private target
51 | end
52 | end
53 | end
54 |
55 | class Array
56 | def with_this_at_front(front_matcher)
57 | case front_matcher
58 | when Array
59 | (front_matcher + self).uniq
60 | when String, Symbol
61 | ([front_matcher] + self).uniq
62 | when Regexp
63 | (self.grep(front_matcher) + self).uniq
64 | else
65 | self
66 | end
67 | end
68 | end
--------------------------------------------------------------------------------
/Support/lib/date_helpers.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'date.rb'
3 | require 'time.rb'
4 |
5 | module FriendlyTime
6 | def to_friendly(time=true)
7 | time=false if Date==self.class
8 |
9 | ret_val = if time
10 | strftime "%b %d, %Y %I:%M %p" + (time=="zone"? " %Z" : "")
11 | else
12 | strftime "%b %d, %Y"
13 | end
14 |
15 | ret_val.gsub(" 0", " ")
16 | end
17 | end
18 |
19 | class Time; include FriendlyTime; end
20 | class Date; include FriendlyTime; end
21 | class DateTime; include FriendlyTime; end
22 |
23 | module DateHelpers
24 | def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false)
25 | from_time = from_time.to_time if from_time.respond_to?(:to_time)
26 | to_time = to_time.to_time if to_time.respond_to?(:to_time)
27 | distance_in_minutes = (((to_time - from_time).abs)/60).round
28 | distance_in_seconds = ((to_time - from_time).abs).round
29 |
30 | case distance_in_minutes
31 | when 0..1
32 | return (distance_in_minutes == 0) ? 'less than a minute' : '1 minute' unless include_seconds
33 | case distance_in_seconds
34 | when 0..4 then '< 5 seconds'
35 | when 5..9 then '< 10 seconds'
36 | when 10..19 then '< 20 seconds'
37 | when 20..39 then '½ minute'
38 | when 40..59 then '< a minute'
39 | else '1 minute'
40 | end
41 |
42 | when 2..44 then "#{distance_in_minutes} minutes"
43 | when 45..89 then '~1 hour'
44 | when 90..1439 then "~#{(distance_in_minutes.to_f / 60.0).round} hours"
45 | when 1440..2879 then '1 day'
46 | when 2880..43199 then "#{(distance_in_minutes / 1440).round} days"
47 | when 43200..86399 then '~1 month'
48 | when 86400..525599 then "#{(distance_in_minutes / 43200).round} months"
49 | when 525600..1051199 then '~1 year'
50 | else "> #{(distance_in_minutes / 525600).round} years"
51 | end
52 | end
53 |
54 | def relative_date(date)
55 | return date if date.is_a?(String)
56 | distance_of_time_in_words(Time.now, date)
57 | end
58 | end
--------------------------------------------------------------------------------
/Commands/Compare Branches.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
11 | require ENV['TM_SUPPORT_PATH'] + '/lib/osx/plist'
12 |
13 | git = Git.new
14 |
15 | branches = git.branch.list(:all)
16 | parameters = { "branches" => branches.map { |e| { "name" => e[:name] } } }
17 |
18 | token = open('|"$DIALOG" -a CompareBranches', 'r+') { |io| io << parameters.to_plist; io.close_write; io.read.chomp }
19 | res = open('|"$DIALOG" -w' + token) { |io| OSX::PropertyList.load(io) }
20 | open('|"$DIALOG" -x' + token) { |io| }
21 |
22 | if res && res['returnArgument']
23 | parent = res['returnArgument'].first['name']
24 | current = res['currentBranch'].first['name']
25 | dispatch(:controller => "diff", :action => "diff", :branches => [parent, current])
26 | end
27 |
28 | input
29 | none
30 | inputFormat
31 | text
32 | name
33 | Compare Branches…
34 | outputCaret
35 | afterOutput
36 | outputFormat
37 | html
38 | outputLocation
39 | newWindow
40 | requiredCommands
41 |
42 |
43 | command
44 | git
45 | locations
46 |
47 | /usr/local/git/bin/git
48 | /opt/local/bin/git
49 | /usr/local/bin/git
50 |
51 | variable
52 | TM_GIT
53 |
54 |
55 | scope
56 | attr.scm.git
57 | semanticClass
58 | action.scm.diff
59 | uuid
60 | E56D4990-B615-4788-A46C-5D0CDE750D56
61 | version
62 | 2
63 |
64 |
65 |
--------------------------------------------------------------------------------
/Support/app/helpers/submodule_helper.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | module SubmoduleHelper
4 | module Update
5 | def with_submodule_updating(&block)
6 | old_modules = get_submodule_hash
7 | begin
8 | yield
9 | ensure
10 | new_modules = get_submodule_hash
11 |
12 | submodule_paths = (new_modules.keys + old_modules.keys).sort.uniq
13 | return if submodule_paths.empty?
14 | submodule_paths.each do |path|
15 | old_module, new_module = old_modules[path], new_modules[path]
16 | case
17 | when old_module && old_module.modified?
18 | puts "Not updating submodule #{new_module.path.inspect}, because it's revision pointer change isn't committed. "
19 | when new_module && ! new_module.cloned?
20 | puts "Cloning new submodule #{new_module.path.inspect} "
21 | puts "#{h new_module.init}\n#{h new_module.update} "
22 | when old_module && ! new_module
23 | puts "Cacheing submodule #{old_module.path.inspect} to #{old_module.git.root_relative_path_for(old_module.abs_cache_path).inspect} "
24 | old_module.cache
25 | when new_module && new_module.cached?
26 | puts "Restoring submodule #{new_module.path.inspect} from cache. "
27 | puts "Restoration failed: a folder is in the way." unless new_module.restore
28 | update_submodule(new_module) if new_module.modified?
29 | when ( ! old_module ) || ( ! old_module.modified? ) && new_module.modified?
30 | puts "Updating submodule #{new_module.path.inspect} "
31 | update_submodule(new_module)
32 | end
33 | flush
34 | end
35 | end
36 | end
37 |
38 | def get_submodule_hash
39 | git.submodule.all.inject({}) { |h, sm| h[sm.path] = sm; h }
40 | end
41 |
42 | def update_submodule(submodule)
43 | puts "#{h submodule.update} "
44 | end
45 | end
46 |
47 | def render_submodule_header(submodule)
48 | puts "... in submodule ‘#{link_to_mate(submodule.path, submodule.git.path)}’ "
49 | end
50 | end
--------------------------------------------------------------------------------
/Support/tmvc/spec/html_helpers_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + "/spec_helper.rb"
2 | describe HtmlHelpers do
3 | def resource_url(arg); arg; end
4 | it "should output a javascript_include_tag" do
5 | javascript_include_tag("prototype.js").should == [""]
6 | end
7 |
8 | it "should format options_for_javascript, escaping appropriately" do
9 | options_for_javascript(:controller => "log", :action => "index", :param => 'Grand "old" time').should == %q!{action: "index", controller: "log", param: "Grand \"old\" time"}!
10 | end
11 |
12 | it "should use dispatch_streaming when update_streaming is passed" do
13 | remote_function(:update_streaming => "iframe", :params => {:controller => "submodule", :action => "create"}, :on_complete => "alert('done')").should ==
14 | %q(dispatch_streaming('iframe', {params: {action: "create", controller: "submodule"}, on_complete: function() { alert('done') }}))
15 | end
16 |
17 | it "should, when called without an :update parameter, render link_to_remote just using dispatch " do
18 | link_to_remote("link", :params => {:controller => "log", :action => "index", :param => 'Grand "old" time'}).should ==
19 | %q(link )
20 | end
21 |
22 | it "should link to javascript" do
23 | link_to_function("click", "alert('Hi!');").should == %q(click )
24 | end
25 |
26 | it "should nest options_for_javascript" do
27 | options_for_javascript({:a => {:b => 1}}).should == "{a: {b: \"1\"}}"
28 | end
29 |
30 | it "should render a button_tag" do
31 | button_tag("Commit", :class => "commit_button").should == %q{ }
32 | end
33 |
34 | it "should create a link with a url" do
35 | link_to_textmate("text", "/hello", 10).should == %q{text }
36 | end
37 |
38 | it "should create a button to a remote" do
39 | button_to_remote("Add", :params => {:controller => "log"}).should include("button")
40 | end
41 | end
--------------------------------------------------------------------------------
/Support/resource/rb_gateway.js:
--------------------------------------------------------------------------------
1 | /* Git JS gateway */
2 | /* Tim Harper (tim.harper at leadmediapartners.org) */
3 | function e_sh(str) {
4 | return '"' + (str.toString().gsub('"', '\\"').gsub('\\$', '\\$')) + '"';
5 | }
6 |
7 | function exec(command, params) {
8 | params = params.map(function(a) { return e_sh(a) }).join(" ")
9 | return TextMate.system(command + " " + params, null)
10 | }
11 |
12 | function ENV(var_name) {
13 | return TextMate.system("echo $" + var_name, null).outputString.strip();
14 | }
15 |
16 | function gateway_command(command, params) {
17 | // var cmd = arguments.shift
18 | // var params = arguments
19 | try {
20 | command = "ruby18 " + e_sh(TM_BUNDLE_SUPPORT) + "/gateway/" + command
21 | return exec(command, params).outputString
22 | }
23 | catch(err) {
24 | return "ERROR!" + err;
25 | }
26 | }
27 |
28 |
29 | function dispatch(params) {
30 | try {
31 | params = $H(params).map(function(pair) { return(pair.key + "=" + pair.value.toString())})
32 | command = "ruby18 " + e_sh(TM_BUNDLE_SUPPORT) + "/dispatch.rb";
33 | // return params.map(function(a) { return e_sh(a) }).join(" ")
34 | return exec(command, params).outputString
35 | }
36 | catch(err) {
37 | return "ERROR!" + err;
38 | }
39 | }
40 |
41 | function dispatch_streaming(iframe_target, options) {
42 | new StreamingDispatchExecuter(iframe_target, options);
43 | return false;
44 | }
45 |
46 | StreamingDispatchExecuter = Class.create();
47 | StreamingDispatchExecuter.prototype = {
48 | initialize: function(iframe_target, options) {
49 | this.options = options;
50 | this.on_complete = options["on_complete"]
51 | params = options['params']
52 | params['streaming']="true"
53 | var parts = dispatch(options['params']).split(",")
54 | this.port = parts[0];
55 | this.pid = parts[1];
56 | $(iframe_target).src = "http://127.0.0.1:" + this.port + "/"
57 | try {
58 | new PeriodicalExecuter(function(pe) {
59 | if (TextMate.system("kill -0 " + this.pid, null).status == 1) {
60 | pe.stop()
61 | if (this.on_complete) this.on_complete();
62 | }
63 | }.bindAsEventListener(this), 0.5)
64 | } catch(e) {$('debug').update(e)}
65 |
66 | },
67 |
68 | }
69 |
70 | TM_BUNDLE_SUPPORT = ENV('TM_BUNDLE_SUPPORT')
--------------------------------------------------------------------------------
/Support/lib/stream_progress_methods.rb:
--------------------------------------------------------------------------------
1 |
2 | module StreamProgressMethods
3 | extend self
4 |
5 | def each_line_from_stream(stream, &block)
6 | line = ""
7 | f = File.open("#{ENV['TMPDIR']}/output", "wb")
8 | stream.each_byte do |char|
9 | f.putc(char)
10 | char = [char].pack('c')
11 | line << char
12 | next unless char=="\n" || char=="\r"
13 | yield line
14 | line = ""
15 | end
16 | yield line
17 | stream
18 | end
19 | protected
20 |
21 | def process_with_progress(stream, options = {}, &block)
22 | options[:start_regexp] ||= /(?-:remote: )?([a-z]+) ([0-9]+) objects/i
23 | options[:progress_regexp] ||= /(?-:(?-:remote: )?([a-z]+) objects: +)?([0-9]+)% \(([0-9]+)\/([0-9]+)\)/i
24 | callbacks = options[:callbacks]
25 | state = nil
26 | each_line_from_stream(stream) do |line|
27 | case line
28 | when options[:start_regexp]
29 | state = $1
30 | callbacks[:start] && callbacks[:start].call(state, $2.to_i)
31 | percentage, index, count = 0, 0, $2.to_i
32 | when options[:progress_regexp]
33 | percentage, index, count = $2.to_i, $3.to_i, $4.to_i
34 | if $1 && state != $1 && percentage != 100
35 | state = $1
36 | callbacks[:start] && callbacks[:start].call(state, count)
37 | end
38 | else
39 | yield line
40 | end
41 |
42 | if state && index
43 | callbacks[:progress] && callbacks[:progress].call(state, percentage, index, count)
44 | if percentage == 100
45 | callbacks[:end] && callbacks[:end].call(state, count)
46 | state = nil
47 | end
48 | end
49 | end
50 | end
51 |
52 | def get_rev_range(input)
53 | revs = input.split("..").compact
54 | revs = ["#{revs[0]}^", revs[0]] if revs.length == 1
55 | revs
56 | end
57 | end
58 |
59 |
60 | module EnhancedStream
61 | def each_line_from_stream(&block)
62 | StreamProgressMethods.each_line_from_stream(self, &block)
63 | end
64 |
65 | def pipe_to(dest)
66 | each_line_from_stream do |line|
67 | dest << line
68 | dest.flush
69 | end
70 | end
71 | end
72 |
73 | IO.send :include, EnhancedStream
74 | StringIO.send :include, EnhancedStream
75 |
--------------------------------------------------------------------------------
/Support/app/controllers/misc_controller.rb:
--------------------------------------------------------------------------------
1 | class MiscController < ApplicationController
2 | layout "application", :only => [:init]
3 | def init
4 | puts "Initializing Git Repository in #{ENV['TM_PROJECT_DIRECTORY']} "
5 | puts htmlize(git.init(ENV["TM_PROJECT_DIRECTORY"]))
6 | end
7 |
8 | def gitk
9 | run_detached("PATH=#{File.dirname(git.git)}:$PATH && gitk --all", "Wish Shell")
10 | end
11 |
12 | def gitgui
13 | run_detached("PATH=#{File.dirname(git.git)}:$PATH && git gui", "Git Gui")
14 | end
15 |
16 | def gitnub
17 | cmd = first_which(git.config["git-tmbundle.gitnub-path"], "nub", "/Applications/GitNub.app/Contents/MacOS/GitNub")
18 | if cmd
19 | run_detached(cmd + " #{ENV['TM_PROJECT_DIRECTORY']}", "Gitnub")
20 | else
21 | puts "Unable to find Gitnub. Use the config dialog to set the Gitnub path to where you've installed it."
22 | output_show_tool_tip
23 | end
24 | end
25 |
26 | def gitx
27 | cmd = first_which(git.config["git-tmbundle.gitx-path"], "gitx", "/Applications/GitX.app/Contents/Resources/gitx")
28 | if cmd
29 | run_detached("cd '#{ENV['TM_DIRECTORY']}';" + cmd, "GitX")
30 | else
31 | puts "Unable to find GitX. Use the config dialog to set the GitX path to where you've installed it."
32 | output_show_tool_tip
33 | end
34 | end
35 |
36 | protected
37 | def first_which(*args)
38 | args.map do |arg|
39 | next if arg.blank?
40 | result = `which '#{arg}'`.strip
41 | return result unless result.empty?
42 | end
43 | nil
44 | end
45 |
46 | def run_detached(cmd, app_name)
47 | exit if fork # Parent exits, child continues.
48 | Process.setsid # Become session leader.
49 | exit if fork # Zap session leader.
50 |
51 | # After this point you are in a daemon process
52 | pid = fork do
53 | STDOUT.reopen(open('/dev/null'))
54 | STDERR.reopen(open('/dev/null'))
55 | Thread.new do
56 | sleep 1.5
57 | %x{osascript -e 'tell app "#{app_name}" to activate'}
58 | exit
59 | end
60 | system(cmd)
61 | end
62 |
63 | Process.detach(pid)
64 | #inspired by http://andrejserafim.wordpress.com/2007/12/16/multiple-threads-and-processes-in-ruby/
65 | end
66 |
67 | end
--------------------------------------------------------------------------------
/Support/spec/controllers/stash_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 |
3 | describe Git::Stash do
4 | before(:each) do
5 | Git.reset_mock!
6 | @stash_controller = StashController.new
7 | StashController.stub!(:new).and_return(@stash_controller)
8 | end
9 |
10 | include SpecHelpers
11 |
12 | it "should ask you if you want to add unstashed files" do
13 | flush
14 | TextMate::UI.should_receive(:alert).with(:warning, "Untracked files in working copy", "Would you like to include the following untracked files in your stash?:\nuntracked_file.txt\nother_untracked_file.txt\n", "Add them", "Leave them out", "Cancel").and_return("Add them")
15 | TextMate::UI.should_receive(:request_string).with({:prompt=>"Describe stash:", :default=>"WIP: ", :title=>"Stash"}).and_return("WIP")
16 |
17 | Git.command_response["ls-files", "-o", "--exclude-per-directory=.gitignore"] = "untracked_file.txt\nother_untracked_file.txt\n"
18 | Git.command_response["stash", "save", "WIP"] = <<-EOF
19 | Saved "mybranch: WIP... msg"
20 | HEAD is now at 7bba918... msg
21 | EOF
22 | output = capture_output do
23 | dispatch(:controller => "stash", :action => "save")
24 | end
25 |
26 | output.should include("Saved \"mybranch: WIP")
27 | Git.commands_ran.should include(["add", "."])
28 | end
29 |
30 |
31 | describe "when applying a stash" do
32 | before(:each) do
33 | @stash_controller.stub!(:select_stash).and_return({:description=>" On master: boogy", :name=>"stash@{0}", :id=>0})
34 | Git.command_response["stash", "list"] = fixture_file("stash_list_response_many_stashes.txt")
35 | Git.command_response["stash", "pop", "stash@{0}"] = fixture_file("status_output.txt")
36 | Git.command_response["stash", "show", "-p", "stash@{0}"] = fixture_file("changed_files.diff")
37 | @output = capture_output do
38 | dispatch(:controller => "stash", :action => "pop")
39 | end
40 |
41 | @h = Hpricot(@output)
42 | end
43 |
44 | it "should show the project status" do
45 | (@h / "table#status_output / tr").length.should == 6
46 | @output.should include("app/views/layouts/application.html.erb")
47 | end
48 |
49 | it "should show a diff of the stash applied" do
50 | (@h / "table.codediff").length.should == 2
51 | end
52 | end
53 | end
54 |
--------------------------------------------------------------------------------
/Support/tmvc/lib/format_helpers/tag_helper.rb:
--------------------------------------------------------------------------------
1 | module FormatHelpers
2 | module TagHelper
3 | # Adapted from RubyOnRails
4 | BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple)
5 | SELF_CLOSABLE_TAGS = %w(img br hr)
6 | def content_tag_string(name, content = nil, options = {}, escape = true, close = true)
7 | if content || ! SELF_CLOSABLE_TAGS.include?(name.to_s)
8 | "#{content_tag_string_open(name, options)}#{content}#{content_tag_string_close(name)}"
9 | else
10 | content_tag_string_open(name, options, true, :self_closing => true)
11 | end
12 | end
13 |
14 | def content_tag_string_open(name, options, escape = true, self_closing = false)
15 | tag_option_string = tag_options(options, escape) if options
16 | "<#{name}#{tag_option_string}#{self_closing ? ' /' : ''}>"
17 | end
18 |
19 | def content_tag_string_close(name)
20 | "#{name}>"
21 | end
22 |
23 | def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
24 | if block_given?
25 | options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
26 | STDOUT << content_tag_string_open(name, options, escape)
27 | yield
28 | STDOUT << content_tag_string_close(name)
29 | else
30 | if content_or_options_with_block.is_a?(Hash)
31 | content = nil
32 | options = content_or_options_with_block
33 | else
34 | content = content_or_options_with_block.to_s
35 | end
36 | content_tag_string(name, content, options, escape)
37 | end
38 | end
39 |
40 | def tag_options(options, escape = true)
41 | unless options.blank?
42 | attrs = []
43 | if escape
44 | options.each do |key, value|
45 | next unless value
46 | key = key.to_s
47 | value = BOOLEAN_ATTRIBUTES.include?(key) ? key : escape_once(value)
48 | attrs << %(#{key}="#{value}")
49 | end
50 | else
51 | attrs = options.map { |key, value| %(#{key}="#{value}") }
52 | end
53 | " #{attrs.sort * ' '}" unless attrs.empty?
54 | end
55 | end
56 |
57 | def htmlize_attr(str)
58 | str.to_s.gsub(/&/, "&").gsub(/"/, """).gsub("<", "<").gsub(">", ">")
59 | end
60 |
61 | alias :escape_once :htmlize_attr
62 |
63 | end
64 | end
--------------------------------------------------------------------------------
/Support/app/views/diff/_diff_result.html.erb:
--------------------------------------------------------------------------------
1 | <%
2 | file_path_right = diff_result[:right][:file_path]
3 | start_line_right = diff_result[:right][:ln_start]
4 |
5 | open_links = {}
6 | files = [:left, :right].map do |lr|
7 | file_path = diff_result[lr][:file_path]
8 | next "(none)" unless file_path
9 |
10 | side_revision = case
11 | when revision.blank? && lr == :right
12 | nil
13 | when revision.blank? && lr == :left
14 | "HEAD"
15 | when revision
16 | lr == :left ? "#{revision}^" : revision
17 | end
18 | open_links[lr] = link_to_remote(lr, :params => { :controller => "log", :action => "open_revision", :file_path => file_path, :revision => side_revision, :line => diff_result[lr][:ln_start], :git_path => git.path })
19 |
20 | file_path_right ? link_to_relative_file(git, file_path_right, start_line_right) : git.root_relative_path_for(file_path)
21 | end
22 | %>
23 |
24 | <%= files.uniq * ' --> ' %>
25 |
26 |
27 |
28 | <%= open_links[:left] %>
29 | <%= open_links[:right] %>
30 |
31 |
32 |
33 |
34 | <% diff_result[:lines].each do |line|
35 | next if @diff_line_count >= Git::DEFAULT_DIFF_LIMIT
36 | @diff_line_count += 1
37 | text = line[:text]
38 | escape_html = true
39 |
40 | line_num_class, row_class = case line[:type]
41 | when :insertion
42 | text = htmlize_highlight_trailing_whitespace(text)
43 | escape_html = false # set to false since the above function escapes HTML
44 | ["", "ins"]
45 |
46 | when :deletion then ["", "del"]
47 | when :eof then ["line-num-eof", "eof"]
48 | when :cut then ["line-num-cut", "cut-line"]
49 | else
50 | ["", "unchanged"]
51 | end
52 |
53 | text = htmlize(text) if escape_html
54 |
55 | ln_right = line[:ln_right]
56 | ln_right = link_to_relative_file(git, diff_result[:right][:file_path], ln_right, ln_right) unless [ :deletion, :eof, :cut ].include?(line[:type])
57 | %>
58 |
59 | <%= line[:ln_left] %>
60 | <%= ln_right %>
61 | <%= text %>
62 | <% end %>
63 |
64 |
65 |
--------------------------------------------------------------------------------
/Syntaxes/Git Rebase Message.tmLanguage:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fileTypes
6 |
7 | git-rebase-todo
8 |
9 | name
10 | Git Rebase Message
11 | patterns
12 |
13 |
14 | captures
15 |
16 | 1
17 |
18 | name
19 | punctuation.definition.comment.git-rebase
20 |
21 |
22 | match
23 | ^\s*(#).*$\n?
24 | name
25 | comment.line.number-sign.git-rebase
26 |
27 |
28 | captures
29 |
30 | 1
31 |
32 | name
33 | support.function.git-rebase
34 |
35 | 2
36 |
37 | name
38 | constant.sha.git-rebase
39 |
40 | 3
41 |
42 | name
43 | meta.commit-message.git-rebase
44 |
45 |
46 | match
47 | ^\s*(pick|p|reword|r|edit|e|squash|s|fixup|f|drop|d)\s+([0-9a-f]+)\s+(.*)$
48 | name
49 | meta.commit-command.git-rebase
50 |
51 |
52 | captures
53 |
54 | 1
55 |
56 | name
57 | support.function.git-rebase
58 |
59 | 2
60 |
61 | patterns
62 |
63 |
64 | include
65 | source.shell
66 |
67 |
68 |
69 |
70 | match
71 | ^\s*(exec|x)\s+(.*)$
72 | name
73 | meta.commit-command.git-rebase
74 |
75 |
76 | captures
77 |
78 | 1
79 |
80 | name
81 | support.function.git-rebase
82 |
83 |
84 | match
85 | ^\s*(break|b)\s*$
86 | name
87 | meta.commit-command.git-rebase
88 |
89 |
90 | scopeName
91 | text.git-rebase
92 | uuid
93 | 7F1CC209-5F6D-486A-8180-09FA282381A1
94 |
95 |
96 |
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 | TODO
2 |
3 | This is a road map to experimental branches and what they should do once they're done.
4 |
5 | Anyone's encouraged to add to this list or take an idea and develop in their own clone of the git repository. When they are completed, notify me (timcharper - at - gmail) to get your changes pulled into the next release branch, and guarantee your name's immortality.
6 |
7 | - cherry-picking --
8 | - pick a SHA ref and merge the commit associated with it from one branch to another
9 | - Would be nice to use the html-log view, and include checkmarks next to each entry. This way, you could browse the log, see the commit message, and check the contents of the commit, making it easier to select which changes you'd like to cherry-pick.
10 | - signing off on commits
11 | - setting up the .gitignore file for a standard rails project
12 | - Rebase command. Have a permanently dismissible dialog to warn Git-newbies about the potential problems of rebasing on a shared repository.
13 | - Centralized branch / tag management page. Have a single, interactive page in textmate where you can switch branches, rebase, merge, diff, log, tag, etc. This will help make the git-menu considerably shorter
14 | - Annotate
15 | - Find a way to clean-up the drop-down (use fixed font, make it a bit smaller, manually truncate the log message so it doesn't get chopped.
16 | - Use "porcelain" format of annotations. Support showing the commit message in the tool-tip hover.
17 | - Follow line numbers when navigating next/previous to assist in tracking a certain piece of code. Have the ability to change the "tracked" line.
18 | - Focus the line number on open dialog
19 | - Show commit message
20 | - Currently, the annotation browser doesn't follow renames (though Git knows about them). It would be nice if the annotation browser was smart enough to figure this out
21 | - It would be nice to be able to change the "current line" in the annotation browser, and have it update as history is navigated (probably would only be possible with next/previous commands).
22 | - Show unpushed changes command
23 | - Show a log of all local commits that have not been pushed to remote branches.
24 | - Make a "branch" management dialog - centralize all branch commands to it.
25 | - Spruce up the stash
26 | - Auto "clear" stash on successful apply
27 | - Central "stash" management page - browse, apply, clear, and create new stash all from one page.
28 | - Choose a stash to delete
29 | - Pull output dialog - make it show the current branch first. Show delimiters to split up sections between branches ( plus margin)
30 | - Log
31 | - ability to search
32 | - Paginate (show more)
33 | - adjust number of context lines (interactively)
34 | - Buttons on every log entry where you can create a tag, branch, or checkout any revision.
35 |
--------------------------------------------------------------------------------
/Support/spec/lib/partial_commit_worker_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 | require LIB_ROOT + "/partial_commit_worker"
3 |
4 | describe PartialCommitWorker do
5 | include SpecHelpers
6 | before(:each) do
7 | @git = Git.singleton_new
8 | end
9 |
10 | describe "Commit" do
11 | before(:each) do
12 | @commit_worker = PartialCommitWorker::Normal.new(@git)
13 | end
14 |
15 | it "should NOT be OK to proceed when not on a branch but performing an initial commit" do
16 | @git.branch.should_receive(:current_name).and_return(nil)
17 | @git.should_receive(:initial_commit_pending?).and_return(false)
18 | @commit_worker.ok_to_proceed_with_partial_commit?.should == false
19 | end
20 |
21 | it "should be OK to proceed when not on a branch but performing an initial commit" do
22 | @git.branch.should_receive(:current_name).and_return(nil)
23 | @git.should_receive(:initial_commit_pending?).and_return(true)
24 | @commit_worker.ok_to_proceed_with_partial_commit?.should == true
25 | end
26 |
27 | it "should be NOT be OK to process when there are no file candidates" do
28 | @commit_worker = @commit_worker
29 | @commit_worker.stub!(:file_candidates).and_return([])
30 | @commit_worker.nothing_to_commit?.should == true
31 | end
32 |
33 | it "should NOT send the last commit message to the commit window when committing" do
34 | @git.stub!(:log).and_return([{:msg => "My Message"}])
35 | @commit_worker.stub!(:file_candidates).and_return([])
36 | @commit_worker.stub!(:status_helper_tool).and_return("/path/to/status_helper_tool")
37 | @output = @commit_worker.tm_scm_commit_window
38 | @output.should_not include(Shellwords.escape("My Message"))
39 | end
40 | end
41 |
42 | describe "Amend" do
43 | before(:each) do
44 | @commit_worker = PartialCommitWorker::Amend.new(@git)
45 | end
46 |
47 | it "should NOT be OK to proceed when performing an initial commit" do
48 | @git.stub!(:initial_commit_pending?).and_return(true)
49 | @commit_worker.nothing_to_amend?.should == true
50 | end
51 |
52 | it "should be OK to amend the commit if there are no files candiates" do
53 | @commit_worker.stub!(:file_candidates).and_return([])
54 | @commit_worker.nothing_to_commit?.should == false
55 | end
56 |
57 | it "should send the last commit message to the commit window when amending" do
58 | @git.stub!(:log).and_return([{:msg => "My Message"}])
59 | @commit_worker.stub!(:file_candidates).and_return([])
60 | @commit_worker.stub!(:status_helper_tool).and_return("/path/to/status_helper_tool")
61 | @output = @commit_worker.tm_scm_commit_window
62 | @output.should include(Shellwords.escape("My Message"))
63 | end
64 | end
65 |
66 | end
67 |
--------------------------------------------------------------------------------
/Support/app/views/annotate/_content.html.erb:
--------------------------------------------------------------------------------
1 | <%
2 | # puts annotations.inspect
3 | last_formatted_line = {}
4 |
5 | range_min, range_max = selected_line_range
6 |
7 | formatted_annotations = annotations.map do |annotation|
8 | line_class = []
9 |
10 | if (range_min == range_max) && range_min == annotation[:ln].to_i
11 | line_class << "selected"
12 | elsif range_min == annotation[:ln].to_i
13 | line_class << "ranged-top"
14 | elsif range_max == annotation[:ln].to_i
15 | line_class << "ranged-bottom"
16 | elsif annotation[:ln].to_i.between?(range_min, range_max)
17 | line_class << "ranged-middle"
18 | end
19 |
20 | line_class << "ins" if annotation[:rev] == "-current-" || annotation[:rev] == revision
21 | line_class = line_class * " "
22 | formatted_line = {
23 | :rev => annotation[:rev],
24 | :author => annotation[:author],
25 | :date => relative_date(annotation[:date]),
26 | :ln => annotation[:ln],
27 | :text => annotation[:text]
28 | }
29 | display = formatted_line.dup
30 |
31 | [:rev, :author, :date].each { |k| display[k] = "…" } if display[:rev]==last_formatted_line[:rev]
32 |
33 | friendly_date = annotation[:date].is_a?(Time) ? annotation[:date].to_friendly : annotation[:date]
34 |
35 | display[:rev_tooltip] = <
46 |
47 |
48 |
49 | <% unless @as_partial %><% end %>
50 |
51 |
52 |
53 |
54 | revision
55 | author
56 | date
57 | line
58 |
59 |
60 |
61 |
62 | <% for display in formatted_annotations %>
63 |
64 |
65 |
66 | <% if display[:rev]=="…" %>
67 | <%= display[:rev] %>
68 | <% else %>
69 | <%= link_to_function display[:rev], "show_annotation('#{display[:rev]}');", :title => htmlize_attr(display[:rev_tooltip]) %>
70 | <% end %>
71 |
72 | <%= make_non_breaking display[:author] %>
73 | <%= make_non_breaking display[:date] %>
74 | <%= display[:ln] %>
75 | <%= htmlize(display[:text]) %>
76 |
77 | <% end %>
78 |
79 |
80 | <% unless @as_partial %>
<% end %>
81 |
--------------------------------------------------------------------------------
/Support/tmvc/tmvc.rb:
--------------------------------------------------------------------------------
1 | TMVC_ROOT = File.dirname(__FILE__)
2 |
3 | ROOT = TMVC_ROOT + "/.."
4 | CONTROLLERS_ROOT = ROOT + "/app/controllers"
5 | HELPERS_ROOT = ROOT + '/app/helpers'
6 | VIEWS_ROOT = ROOT + "/app/views"
7 |
8 |
9 | %w[string hash erb_stdout ruby_tm_helpers format_helpers/tag_helper html_helpers application_helper application_controller].each do |filename|
10 | require TMVC_ROOT + "/lib/#{filename}.rb"
11 | end
12 |
13 | require(HELPERS_ROOT + "/application_helper.rb") if File.exist?(HELPERS_ROOT + "/application_helper.rb")
14 |
15 |
16 | at_exit {
17 | if $exit_status
18 | exit $exit_status
19 | end
20 | }
21 |
22 | module TMVC
23 | class << self
24 | attr_accessor :catch_exceptions
25 | def dispatch_streaming(params = {})
26 | require 'socket'
27 | streaming = params.delete(:streaming)
28 | try_count = 0
29 | port = 0
30 | begin
31 | port = 9999 + try_count
32 | server = TCPServer.new('', port)
33 | rescue => e
34 | try_count += 1
35 | retry if try_count < 10
36 | raise "Couldn't find a port!"
37 | end
38 |
39 | pid = fork do
40 | socket = server.accept
41 | Object.send :remove_const, 'STDOUT'
42 | Object.const_set("STDOUT", socket)
43 | dispatch_normal(params)
44 | end
45 | puts "#{port},#{pid}"
46 | flush
47 | end
48 |
49 | def dispatch_normal(params = {})
50 | # puts "hi"
51 | # return false
52 | begin
53 | raise "must supply a controller to use!" unless controller = params[:controller]
54 | params[:action] ||= "index"
55 | controller_class = "#{controller}_controller".classify.constantize
56 | controller_class.call(params[:action], params)
57 | rescue => e
58 | raise e unless $dont_catch_exceptions
59 | puts htmlize($!)
60 | puts htmlize($!.backtrace)
61 | end
62 | end
63 |
64 | def dispatch(params = {})
65 | $dispatched = true
66 | params = parse_dispatch_args(ARGV) if params.is_a?(Array)
67 | if debug_mode
68 | require 'logger'
69 | Logger.new(ROOT + "/log/dispatch.log").warn(params.inspect)
70 | end
71 | if params[:streaming]
72 | dispatch_streaming(params)
73 | else
74 | dispatch_normal(params)
75 | end
76 | end
77 |
78 | def parse_dispatch_args(args = [])
79 | params = args.inject({}) do |hash, arg|
80 | parts = arg.scan(/(.+?)=(.+)/m).flatten
81 | next hash if parts.empty?
82 | key = parts.first.to_sym
83 | value = parts.last
84 | hash[key] = value
85 | hash
86 | end
87 | end
88 | end
89 | self.catch_exceptions = true
90 | end
91 |
92 | def debug_mode
93 | return $debug_mode unless $debug_mode.nil?
94 | $debug_mode = File.exist?(File.join(ROOT, "/DEBUG"))
95 | end
96 | def dispatch(params = {}); TMVC.dispatch(params); end
--------------------------------------------------------------------------------
/README.textile:
--------------------------------------------------------------------------------
1 | h1. The Git Textmate Bundle
2 |
3 | h2. Installation
4 |
5 | You can install this bundle in TextMate by opening the preferences and going to the bundles tab. After installation it will be automatically updated for you.
6 |
7 | * Many shortcuts are available from the SCM shortcut ⌘Y Subversion commands are ⌘⌥G. Less frequent commands are accessed via the menu.
8 |
9 | h2. Support
10 |
11 | * "Issue tracker":https://github.com/textmate/git.tmbundle/issues
12 | * "Repository":https://github.com/textmate/git.tmbundle
13 |
14 | The "Mailing list":http://groups.google.com/group/git-tmbundle has now been closed. Please feel free to report issues using the "Issue tracker":https://github.com/textmate/git.tmbundle/issues.
15 |
16 | h2. Theme notes:
17 |
18 | The "Git Commit Message" Language defines two scopes that can be used by a theme to generate "line too long" warnings for the first line of the commit:
19 |
20 | * invalid.deprecated.line-too-long.git-commit
21 | * invalid.illegal.line-too-long.git-commit
22 |
23 | The warning scope triggers when the first line exceeds 50 characters; the error scope over 65 characters. These aren't generally-used TextMate scopes, so you can add new rules to your preferred themes, such as orange background/red background. You can also edit the regex to change the preferred character counts.
24 |
25 | h2. Development
26 |
27 | h3. Running Specs
28 |
29 | The specs must be run with Ruby 1.8.7 (p358). Use your Ruby version manager of choice to install this version. Then, with this version activated (and @Support/@ as current directory), run @gem install --file Gemfile@ to install the appropriate versions of RSpec and hpricot.
30 |
31 | When running the specs from the command line you need to set @TM_SUPPORT_PATH@ explicitly. The following should work:
32 |
33 |
34 | export TM_SUPPORT_PATH=~/Library/Application\ Support/TextMate/Managed/Bundles/Bundle\ Support.tmbundle/Support/shared
35 |
36 |
37 | To run the specs then use:
38 |
39 |
40 | spec spec/
41 |
42 |
43 | h2. Who:
44 |
45 | h3. Previous Maintainers
46 |
47 | * January 2010 - 2012: "James Conroy-Finn":http://jamesconroyfinn.com/
48 | * January 2008 - December 2009: "Tim Harper":http://tim.theenchanter.com/ (with "Lead Media Partners":http://leadmediapartners.com).
49 |
50 | h2. Git-tmbundle superstars
51 |
52 | The Git TextMate Bundle wouldn't be possible without the contributions of the following fine gentlemen:
53 |
54 | h3. Major Contributions
55 |
56 | * Allan Odgaard - Started the bundle, got it rolling. Many patches. Oh, and TextMate :-).
57 | * Sam Granieri - GitK, Many of the git-svn commands, Git initialize repository command, menu layouting, create-tag.
58 | * Johan Sørensen - Contributing the CSS styling.
59 |
60 | Please feel free to send a pull request if you've added any functionality to this bundle that you think the rest of the git-loving, TextMate-using world would appreciate!
61 |
--------------------------------------------------------------------------------
/Commands/Git Resolve Conflicts.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beforeRunningCommand
6 | nop
7 | command
8 | #!/usr/bin/env ruby18
9 |
10 | # Resolve conflicts command for git/FileMerge
11 | # By Tim Harper
12 | # http://code.leadmediapartners.com/
13 |
14 | require "fileutils"
15 | FM="#{`"$TM_SUPPORT_PATH/bin/find_app" FileMerge.app`}/Contents/MacOS/FileMerge"
16 | require ENV['TM_BUNDLE_SUPPORT'] + '/environment.rb'
17 | require ENV['TM_SUPPORT_PATH'] + '/lib/escape.rb'
18 |
19 | state = :both
20 |
21 | input_file_path = ENV['TM_FILEPATH']
22 | input_filename = File.basename(input_file_path)
23 |
24 | input = $<.read
25 |
26 | left = ""
27 | right = ""
28 |
29 |
30 | input.each { |line|
31 | if /^(<{7}|={7}|>{7})($| )/.match(line)
32 | state =
33 | case $1
34 | when "<<<<<<<" then :left
35 | when "=======" then :right
36 | when ">>>>>>>" then :both
37 | end
38 | next
39 | end
40 | left << line if state == :left || state == :both
41 | right << line if state == :right || state == :both
42 | }
43 |
44 | if left==right
45 | puts "No conflicts to resolve in #{input_file_path}."
46 | exit
47 | end
48 |
49 | filename = "git-conflict-resolve"
50 | tmp_path = "#{ENV['TMPDIR']}/git-conflict-resolve/"
51 |
52 | FileUtils.rm_rf(tmp_path)
53 | FileUtils.mkdir_p(tmp_path)
54 |
55 | left_file = "#{tmp_path}left-#{input_filename}.rb"
56 | right_file = "#{tmp_path}right-#{input_filename}.rb"
57 | File.open(left_file, "w") { |f| f.puts left }
58 | File.open(right_file, "w") { |f| f.puts right }
59 |
60 | %x{#{FM} -left #{e_sh left_file} -right #{e_sh right_file} -merge #{e_sh input_file_path} &>/dev/null & }
61 |
62 | input
63 | document
64 | inputFormat
65 | text
66 | name
67 | Edit Conflicts With FileMerge…
68 | outputCaret
69 | afterOutput
70 | outputFormat
71 | text
72 | outputLocation
73 | toolTip
74 | requiredCommands
75 |
76 |
77 | command
78 | git
79 | locations
80 |
81 | /usr/local/git/bin/git
82 | /opt/local/bin/git
83 | /usr/local/bin/git
84 |
85 | variable
86 | TM_GIT
87 |
88 |
89 | scope
90 | attr.scm.git
91 | semanticClass
92 | action.scm.conflicts
93 | uuid
94 | 7CE2C842-EBC4-443C-8DDB-3B16AC593D9A
95 | version
96 | 2
97 |
98 |
99 |
--------------------------------------------------------------------------------
/Support/spec/lib/commands/config_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../spec_helper'
2 |
3 | describe SCM::Git do
4 | before(:each) do
5 | @git = SCM::Git.new
6 | Git.reset_mock!
7 | end
8 |
9 | it "should let git decide when local/global not specified" do
10 | Git.command_response["config", "remote.origin.url"] = "../origin"
11 | value = @git.config["remote.origin.url"]
12 | Git.commands_ran.first.should == ["config", "remote.origin.url"]
13 | value.should == "../origin"
14 | end
15 |
16 | it "should default to local when writing" do
17 | Git.command_response["config", "remote.origin.url", "../origin"] = ""
18 | @git.config["remote.origin.url"] = "../origin"
19 | Git.commands_ran.first.should == ["config", "remote.origin.url", "../origin"]
20 | end
21 |
22 | it "should allow reading of local values" do
23 | Git.command_response["config", "--file", "/base/.git/config", "remote.origin.url"] = "../origin"
24 | value = @git.config[:local, "remote.origin.url"]
25 | Git.commands_ran.first.should == ["config", "--file", "/base/.git/config", "remote.origin.url"]
26 | value.should == "../origin"
27 | end
28 |
29 | it "should allow writing of local values" do
30 | Git.command_response["config", "--file", "/base/.git/config", "remote.origin.url", "../origin"] = ""
31 | @git.config[:local, "remote.origin.url"] = "../origin"
32 | Git.commands_ran.first.should == ["config", "--file", "/base/.git/config", "remote.origin.url", "../origin"]
33 | end
34 |
35 | it "should delete local values when assigning nil" do
36 | @git.config[:local, "git-tmbundle.log.limit"] = nil
37 | Git.commands_ran.first.should == ["config", "--file", "/base/.git/config", "--unset", "git-tmbundle.log.limit"]
38 | end
39 |
40 | it "should allow reading global values" do
41 | Git.command_response["config", "--global", "remote.origin.url"] = "../origin"
42 | value = @git.config[:global, "remote.origin.url"]
43 | Git.commands_ran.first.should == ["config", "--global", "remote.origin.url"]
44 | value.should == "../origin"
45 | end
46 |
47 | it "should raise when given a scope it doesn't understand" do
48 | lambda { @git.config[:boogy, "remote.origin.url"] }.should raise_error("I don't understand the scope :boogy")
49 | end
50 |
51 | it "should respond to the string version of global as well as the symbol" do
52 | Git.command_response["config", "--global", "remote.origin.url"] = "../origin"
53 | @git.config[:global, "remote.origin.url"].should == "../origin"
54 | @git.config["global", "remote.origin.url"].should == "../origin"
55 | end
56 |
57 | it "should allow writing global values" do
58 | Git.command_response["config", "--global", "remote.origin.url", "../origin"] = ""
59 | @git.config[:global, "remote.origin.url"] = "../origin"
60 | Git.commands_ran.first.should == ["config", "--global", "remote.origin.url", "../origin"]
61 | end
62 |
63 | it "should return nil on blank, non-existing value" do
64 | Git.command_output << ""
65 | @git.config["remote.origin.url"].should be_nil
66 | end
67 | end
--------------------------------------------------------------------------------
/Support/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | SPEC_ROOT = File.dirname(__FILE__)
2 | FIXTURES_DIR = "#{SPEC_ROOT}/fixtures"
3 | require SPEC_ROOT + '/../environment.rb'
4 | require 'rubygems'
5 | require 'stringio'
6 | require 'hpricot'
7 | require SPEC_ROOT + "/../tmvc/spec/spec_helpers.rb"
8 | require LIB_ROOT + "/ui.rb"
9 | SpecHelpers::PUTS_CAPTURE_CLASSES << ::Git
10 |
11 | describe "Formatter with layout", :shared => true do
12 | before(:each) do
13 | @h = Hpricot(@output)
14 | end
15 |
16 | it "should include a style.css" do
17 | (@h / "link").map{|s| File.basename(s.attributes["href"])}.should include("style.css")
18 | end
19 |
20 | it "should include a prototype.js" do
21 | (@h / "script").map{|s| File.basename(s.attributes["src"].to_s)}.should include("prototype.js")
22 | end
23 | end
24 |
25 | class ArrayKeyedHash < Hash
26 | def []=(*args)
27 | value = args.pop
28 | super(args, value)
29 | end
30 |
31 | def [](*args)
32 | super(args)
33 | end
34 | end
35 |
36 | class Git
37 | alias :initialize_without_autopath :initialize
38 | def initialize(options = {})
39 | options = options.dup
40 | options[:path] ||= "/base"
41 | initialize_without_autopath(options)
42 | end
43 |
44 | class << self
45 | def reset_mock!
46 | command_response.clear
47 | command_output.clear
48 | commands_ran.clear
49 | end
50 |
51 | def command_response
52 | @@command_response ||= ArrayKeyedHash.new
53 | end
54 |
55 | def command_output
56 | @@command_output ||= []
57 | end
58 |
59 | def commands_ran
60 | @@commands_ran ||= []
61 | end
62 |
63 | def stubbed_command(*args)
64 | commands_ran << args
65 | if command_response.empty?
66 | command_output.shift
67 | else
68 | r = command_response[*args] || ""
69 | if r.is_a?(Array)
70 | r.shift
71 | else
72 | r
73 | end
74 | end
75 | end
76 | end
77 |
78 | def command(*args)
79 | Git.stubbed_command(*args)
80 | end
81 |
82 | def popen_command(*args)
83 | StringIO.new(command(*args))
84 | end
85 |
86 | def git_dir(file_or_dir = paths.first)
87 | "/base/.git"
88 | end
89 |
90 | def paths(*args)
91 | [path]
92 | end
93 |
94 | def nca(*args)
95 | path
96 | end
97 |
98 | attr_writer :version
99 | def version; @version ||= "1.5.4.3"; end
100 | end
101 |
102 | def exit_with_output_status
103 | end
104 |
105 | [:exit_show_html, :exit_discard, :exit_show_tool_tip].each do |exit_method|
106 | Object.send :define_method, exit_method do
107 | $exit_status = Object.const_get(exit_method.to_s.upcase)
108 | end
109 | end
110 |
111 | class Object
112 | def self.singleton_new(*args)
113 | new_obj = new(*args)
114 | self.stub!(:new).and_return(new_obj)
115 | new_obj
116 | end
117 | end
118 |
119 | module TextMate::UI
120 | def self.request_item(options = {}, &block)
121 | yield options[:items].first if block_given?
122 | options[:items].first
123 | end
124 | end
--------------------------------------------------------------------------------
/Support/spec/controllers/log_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 | require CONTROLLERS_ROOT + "/log_controller.rb"
3 | describe LogController do
4 | include SpecHelpers
5 |
6 | before(:each) do
7 | Git.reset_mock!
8 | @git = Git.singleton_new
9 | end
10 |
11 | describe "showing a log" do
12 | before(:each) do
13 | Git.command_response["log", "--date=default", "--format=medium", "-n", Git::Config::DEFAULT_LOG_LIMIT, "."] = fixture_file("log.txt")
14 | @git.branch.stub!(:current).and_return branch_stub(:name => "refs/heads/master")
15 | @output = capture_output do
16 | dispatch :controller => "log", :action => "index", :path => "."
17 | end
18 | end
19 |
20 | it "should include render with a layout" do
21 | @output.should include("")
22 | end
23 |
24 | it "should show a log" do
25 | @output.should include("198fc930 ")
26 | end
27 | end
28 |
29 | describe "showing outgoing changes" do
30 | before(:each) do
31 | @controller = LogController.singleton_new
32 | @git = Git.singleton_new
33 |
34 | @master = branch_stub(:name => "refs/heads/master", :tracking_status => :behind, :tracking_branch_name => "refs/remotes/origin/master")
35 | @release = branch_stub(:name => "refs/heads/release", :tracking_status => :ahead, :tracking_branch_name => "refs/remotes/origin/release")
36 | @task = branch_stub(:name => "refs/heads/task", :tracking_status => :diverged, :tracking_branch_name => "refs/remotes/origin/task")
37 | end
38 |
39 | it "should show an outgoing log for all diverged or ahead branches" do
40 | @git.branch.stub!(:all).and_return([@master, @release, @task])
41 | @git.submodule.stub!(:all).and_return([])
42 |
43 | @controller.should_receive(:render_component).with(:action => "log", :git_path => @git.path, :branches => "refs/remotes/origin/release..refs/heads/release")
44 | @controller.should_receive(:render_component).with(:action => "log", :git_path => @git.path, :branches => "refs/remotes/origin/task..refs/heads/task")
45 |
46 | capture_output do
47 | dispatch :controller => "log", :action => "outgoing"
48 | end
49 | end
50 |
51 | it "should show an outgoing branch log for all submodules" do
52 | @git.branch.stub!(:all).and_return([])
53 | @submodule = stub("submodule",
54 | :git => stub("git",
55 | :path => "submodule_path",
56 | :branch => stub("branch_command",
57 | :all => [@master, @release, @task]
58 | )
59 | )
60 | )
61 |
62 | @git.submodule.stub!(:all).and_return([@submodule])
63 |
64 | @controller.should_receive(:render_component).with(:action => "log", :git_path => @submodule.git.path, :branches => "refs/remotes/origin/release..refs/heads/release")
65 | @controller.should_receive(:render_component).with(:action => "log", :git_path => @submodule.git.path, :branches => "refs/remotes/origin/task..refs/heads/task")
66 |
67 | capture_output do
68 | dispatch :controller => "log", :action => "outgoing"
69 | end
70 | end
71 | end
72 | end
--------------------------------------------------------------------------------
/Support/app/views/annotate/index.html.erb:
--------------------------------------------------------------------------------
1 | <% render "_navigate_box", :locals => { :log_entries => @log_entries, :revision => @revision } %>
2 | <% render "_content", :locals => { :annotations => @annotations, :revision => @revision } %>
3 |
4 | <% content_for :javascript do %>
5 |
87 | <% end %>
--------------------------------------------------------------------------------
/Support/spec/lib/commands/status_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../spec_helper'
2 |
3 | describe SCM::Git do
4 | before(:each) do
5 | @git = Git.new
6 | Git.command_response["status", "--porcelain"] = fixture_file("status_output.txt")
7 | end
8 |
9 | include SpecHelpers
10 |
11 | it "should return the state of an initial_commit_pending? as false" do
12 | @git.initial_commit_pending?.should == false
13 | end
14 |
15 | it "should return the state of initial_commit_pending? as true when 'git status' reports it as such" do
16 | Git.command_response["status"] = <"?",
81 | "new_file_and_added.txt"=>"A",
82 | "small.diff"=>"D",
83 | "directory.txt"=>"?",
84 | "project.txt"=>"M",
85 | "app/views/layouts/application.html.erb" => "R"
86 |
87 | }
88 | end
89 |
90 | it "should recognize conflict markers" do
91 | @git.file_has_conflict_markers("#{FIXTURES_DIR}/conflict.txt").should == true
92 | @git.file_has_conflict_markers("#{FIXTURES_DIR}/log.txt").should == false
93 | end
94 | end
--------------------------------------------------------------------------------
/Support/tmvc/lib/ruby_tm_helpers.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: UTF-8 -*0
2 | # TextMate helpers
3 | # Author: Tim Harper with Lead Media Partners.
4 | # http://code.google.com/p/productivity-bundle/
5 |
6 | if ENV.has_key? 'TM_SUPPORT_PATH'
7 | require "#{ENV["TM_SUPPORT_PATH"]}/lib/escape"
8 | else
9 | abort(<<-PLAIN.gsub(/^\s{0,4}/, ''))
10 |
11 | \e[31mFail whale detected!\e[0m
12 |
13 | TM_SUPPORT_PATH is not set. This is probably because you are running
14 | specs from outside of TextMate.
15 |
16 | You can set TM_SUPPORT_PATH using something like...
17 |
18 | export TM_SUPPORT_PATH='/Applications/TextMate.app/Contents/SharedSupport/Support'
19 |
20 | PLAIN
21 | end
22 |
23 | public
24 |
25 | EXIT_DISCARD = 200
26 | EXIT_SHOW_HTML = 205
27 | EXIT_SHOW_TOOL_TIP = 206
28 |
29 | def exit_discard
30 | exit 200;
31 | end
32 |
33 | def exit_replace_text
34 | exit 201;
35 | end
36 |
37 | def exit_replace_document
38 | exit 202;
39 | end
40 |
41 | def exit_insert_text
42 | exit 203;
43 | end
44 |
45 | def exit_insert_snippet
46 | exit 204;
47 | end
48 |
49 | def exit_show_html
50 | exit 205
51 | end
52 |
53 | def exit_show_tool_tip
54 | exit 206;
55 | end
56 |
57 | def exit_create_new_document
58 | exit 207;
59 | end
60 |
61 | def flush; $>.flush; STDOUT.flush; end;
62 |
63 | def tm_open(file, options = {})
64 | line = options[:line]
65 | wait = options[:wait]
66 | if line.nil? && /^(.+):(\d+)$/.match(file)
67 | file = $1
68 | line = $2
69 | end
70 |
71 | unless /^\//.match(file)
72 | file = File.join((ENV['TM_PROJECT_DIRECTORY'] || Dir.pwd), file)
73 | end
74 |
75 | args = []
76 | args << "-w" if wait
77 | args << e_sh(file)
78 | args << "-l #{line}" if line
79 | %x{"#{ENV['TM_SUPPORT_PATH']}/bin/mate" #{args * " "}}
80 | end
81 |
82 |
83 | # this method only applies when the whole document contents are sent in
84 | def tm_expanded_selection(options = {})
85 | text=ENV['TM_SELECTED_TEXT'].to_s
86 | return text unless text.empty?
87 |
88 | options = {
89 | :input_type => :doc,
90 | :input => nil,
91 | :forward => /\w*/i,
92 | :backward => /\w*/i,
93 | :line_number => ENV['TM_LINE_NUMBER'].to_i,
94 | :col_number => ENV['TM_COLUMN_NUMBER'].to_i
95 | }.merge(options)
96 |
97 | col_number, line_number = options[:col_number], options[:line_number]
98 |
99 | doc = options[:input] ||= $stdin.read
100 |
101 | line =
102 | case options[:input_type]
103 | when :doc then doc.split("\n")[line_number - 1]
104 | when :line then doc
105 | else
106 | raise "Can't handle input_type #{options[:input_type]} for tm_expanded_selection"
107 | end
108 |
109 | last_part = line[ (col_number - 1)..-1]
110 | first_part = line[ 0..col_number - 2]
111 |
112 | last_part.gsub!(/^(#{options[:forward]}){0,1}.*$/i) { $1 }
113 |
114 | first_part.reverse!
115 | first_part.gsub!(/^(#{options[:backward]}){0,1}.*$/i) { $1 }
116 | first_part.reverse!
117 | first_part + last_part
118 | end
119 |
120 |
121 |
122 | module Enumerable
123 | # TODO remove when 1.9 supports natively
124 | def map_with_index
125 | result = []
126 | each_with_index do |item, idx|
127 | result << yield(item, idx)
128 | end
129 | result
130 | end
131 | end
132 |
133 | class Object
134 | def blank?
135 | nil? || empty?
136 | end
137 | end
138 |
--------------------------------------------------------------------------------
/Support/tmvc/lib/html_helpers.rb:
--------------------------------------------------------------------------------
1 | module HtmlHelpers
2 | include ERB::Util
3 |
4 | def path_for(default_path, path)
5 | if path.include?("/")
6 | path
7 | else
8 | default_path(path)
9 | end
10 | end
11 |
12 | protected
13 | def resource_url(filename)
14 | "file://" + e_url("#{ENV['TM_BUNDLE_SUPPORT']}/resource/#{filename}")
15 | end
16 |
17 | def select_box(name, select_options = [], options = {})
18 | options[:name] ||= name
19 | options[:id] ||= name
20 | # puts select_options.inspect
21 | <<-EOF
22 |
23 | #{select_options}
24 |
25 | EOF
26 | end
27 |
28 | def options_for_select(select_options = [], selected_value = nil)
29 | output = ""
30 |
31 | select_options.each do |name, val, filepath|
32 | selected = (val == selected_value) ? "selected='true'" : ""
33 | output << "#{htmlize(name)} "
34 | end
35 |
36 | output
37 | end
38 |
39 | def make_non_breaking(output)
40 | htmlize(output.to_s.strip).gsub(" ", " ")
41 | end
42 |
43 |
44 | def e_js(str)
45 | str.to_s.gsub(/"/, '\"').gsub("\n", '\n')
46 | end
47 |
48 | def javascript_include_tag(*params)
49 | file_names = []
50 | params = params.map {|p| p.include?(".js") ? p : "#{p}.js"}
51 | params.map do |p|
52 | content_tag :script, "", :type => "text/javascript", :src => resource_url(p)
53 | end * ""
54 | end
55 |
56 | def options_for_javascript(options = {})
57 | output = options.map { |key, value| "#{key}: " + (value.is_a?(Hash) ? options_for_javascript(value) : "\"#{e_js(value)}\"") }
58 | "{" + (output.sort * ", ") + "}"
59 | end
60 |
61 | def remote_function(options = {})
62 | case
63 | when options[:update]
64 | "$('#{options[:update]}').update(dispatch(#{options_for_javascript(options[:params])}))"
65 | when target = options[:update_streaming]
66 | other_options = ""
67 | other_options << ", on_complete: function() { #{options[:on_complete]} }" if options[:on_complete]
68 |
69 | "dispatch_streaming('#{target}', {params: #{options_for_javascript(options[:params])}#{other_options}})"
70 | else
71 | "dispatch(#{options_for_javascript(options[:params])})"
72 | end
73 | end
74 |
75 | def link_to_remote(name, options = {})
76 | link_to_function(name, remote_function(options))
77 | end
78 |
79 | def link_to_function(name, js, html_options = {})
80 | content_tag(:a, name, {:href => "javascript:void(0)", :onclick => js}.merge(html_options))
81 | end
82 |
83 | def button_tag(value, options = {})
84 | content_tag(:input, {:type => "button", :name => value, :value => value }.merge(options))
85 | end
86 |
87 | def link_to_textmate(name, file, line = nil)
88 | content_tag(:a, name, :href => "txmt://open?url=file://#{e_url file}&line=#{line}")
89 | end
90 |
91 | def button_to_remote(name, options = {}, html_options = {})
92 | button_tag(name, {:onclick => remote_function(options)}.merge(html_options))
93 | end
94 |
95 | def link_to_mate(name, file)
96 | link_to_function(name, "exec('mate', [\"#{e_sh(file)}\"])")
97 | end
98 |
99 | include FormatHelpers::TagHelper
100 | end
101 |
102 |
--------------------------------------------------------------------------------
/Support/spec/lib/commands/pull_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../spec_helper'
2 |
3 | require 'stringio'
4 |
5 | describe Git do
6 | include SpecHelpers
7 |
8 | before(:each) do
9 | @pull = Git.new
10 | Git.reset_mock!
11 | Git.command_response["branch"] = "* master\n task"
12 | end
13 |
14 | describe "push from git 1.5.3.4" do
15 | before(:each) do
16 | @process_io = StringIO.new <<-EOF
17 | Unpacking 6 objects...
18 | 16% (1/6) done\r 33% (2/6) done\r 50% (3/6) done\r 66% (4/6) done\r 83% (5/6) done\r 100% (6/6) done\n
19 | * refs/remotes/origin/master: fast forward to branch 'master' of /Users/timcharper/projects/origin
20 | old..new: a58264f..89e8f37
21 | * refs/remotes/origin/mybranch: storing branch 'mybranch' of /Users/timcharper/projects/origin
22 | commit: d8b3683
23 | You asked me to pull without telling me which branch you
24 | want to merge with, and 'branch.asdf.merge' in
25 | your configuration file does not tell me either. Please
26 | name which branch you want to merge on the command line and
27 | try again (e.g. 'git pull ').
28 | See git-pull(1) for details on the refspec.
29 |
30 | If you often merge with the same branch, you may want to
31 | configure the following variables in your configuration
32 | file:
33 | EOF
34 | end
35 |
36 | it "should call the status proc 6 times" do
37 | started_count = {}
38 | finished = {}
39 | output = {"Unpacking" => [] }
40 | @pull.process_pull(@process_io,
41 | :start => lambda { |state, count| started_count[state] = count },
42 | :progress => lambda {|state, percent, index, count| output[state] << [percent, index, count]},
43 | :end => lambda { |state, count| finished[state] = true }
44 | )
45 |
46 | for state in ["Unpacking"]
47 | started_count[state].should == 6
48 | output[state].map{|o| o[0]}.should == [0,16,33,50,66,83,100]
49 | output[state].map{|o| o[1]}.should == (0..6).to_a
50 | output[state].map{|o| o[2]}.should == [6] * 7
51 | finished[state].should == true
52 | end
53 | end
54 |
55 | it "should return a list of all revisions pulled" do
56 | output = @pull.process_pull(@process_io)
57 | output[:pulls].should == {
58 | "refs/remotes/origin/master" => ["a58264f", "89e8f37"],
59 | "refs/remotes/origin/mybranch" => ["d8b3683^", "d8b3683"]
60 | }
61 | end
62 |
63 | it "should return :nothing_to_pull if Everything up-to-date" do
64 | output = @pull.process_pull(StringIO.new("Already up-to-date.\n"))
65 | output[:nothing_to_pull].should == true
66 | end
67 | end
68 |
69 | describe "for git 1.5.4.3" do
70 | before(:each) do
71 | @process_io = StringIO.new(fixture_file("pull_1_5_4_3_output.txt"))
72 | end
73 |
74 | it "should call the progress proc 6 times for state Compressing" do
75 | output = {"Compressing" => [] }
76 |
77 | @pull.process_pull(@process_io, :progress => lambda {|state, percent, index, count| output[state] << [percent, index, count]})
78 | output["Compressing"].map{|o| o[0]}.should == [16,33,50,66,83,100]
79 | output["Compressing"].map{|o| o[1]}.should == (1..6).to_a
80 | output["Compressing"].map{|o| o[2]}.should == [6] * 6
81 | end
82 |
83 | it "should extract the pull information for the branch and assume the current branch" do
84 | output = @pull.process_pull(@process_io)
85 | output[:pulls]['asdf'].should == ["dc29d3d", "05f9ad9"]
86 | output[:pulls]['master'].should == ["791a587", "4bfc230"]
87 |
88 | end
89 | end
90 |
91 | end
92 |
--------------------------------------------------------------------------------
/Support/spec/lib/commands/diff_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../spec_helper'
2 |
3 | describe Git do
4 | before(:each) do
5 | @diff = Git.new
6 | end
7 | include SpecHelpers
8 | describe "when parsing a diff" do
9 | before(:each) do
10 | @results = @diff.parse_diff(fixture_file("changed_files.diff"))
11 | @lines = @results.first[:lines]
12 | end
13 |
14 | it "should create an entry for each file" do
15 | @results.should have(2).results
16 | @results.map{|r| r[:left][:file_path]}.should == ["Support/lib/commands/diff.rb", "Support/lib/formatters/diff.rb"]
17 | @results.map{|r| r[:right][:file_path]}.should == ["Support/lib/commands/diff.rb", "Support/lib/formatters/diff.rb"]
18 | end
19 |
20 | it "should parse the line_numbers for the files" do
21 | @lines.map{|l| l[:ln_left]}.should ==
22 | (5..7).to_a +
23 | [8] +
24 | ([nil] * 20) +
25 | (9..10).to_a +
26 | ["EOF"]
27 |
28 | @lines.map{|r| r[:ln_right]}.should ==
29 | (5..7).to_a +
30 | [nil] +
31 | (8..27).to_a +
32 | (28..29).to_a +
33 | ["EOF"]
34 | end
35 |
36 | it "shouldn't count the (\\ No newline at end of file) line" do
37 | @lines.last[:text].should == "No newline at end of file"
38 | @lines.last[:ln_right].should == "EOF"
39 | @lines.last[:ln_left].should == "EOF"
40 | end
41 |
42 | it "should parse the file mode" do
43 | @results.first[:mode].should == "100644"
44 | end
45 | end
46 |
47 | describe "when parse a diff with line breaks" do
48 | before(:each) do
49 | @results = @diff.parse_diff(fixture_file("changed_files_with_break.diff"))
50 | @lines = @results.first[:lines]
51 | end
52 |
53 | it "should insert a line break" do
54 | @lines.map{|t| t[:type]}.should include(:cut)
55 | end
56 | end
57 | describe "when parse a diff with line breaks" do
58 | before(:each) do
59 | @results = @diff.parse_diff(fixture_file("new_line_at_end.diff"))
60 | @lines = @results.first[:lines]
61 | end
62 |
63 | it "should show EOF as occuring for the side that previously had line-numbers" do
64 | eof_line = @lines.find{|l| l[:type]==:eof}
65 | eof_line[:ln_left].should == "EOF"
66 | eof_line[:ln_right].should == nil
67 | end
68 | end
69 |
70 | describe "when parsing small diff" do
71 | before(:each) do
72 | @results = @diff.parse_diff(fixture_file("small.diff"))
73 | @lines = @results.first[:lines]
74 | end
75 |
76 | it "should start with line-number-zero" do
77 | @lines.map{|l| l[:ln_left]}.should == [1, "EOF", nil, nil, nil, nil]
78 | @lines.map{|l| l[:ln_right]}.should == [nil, nil, 1, 2, 3, "EOF"]
79 | end
80 | end
81 |
82 | describe "parsing new and deleted files" do
83 | before(:each) do
84 | @results = @diff.parse_diff(fixture_file("submodules.diff"))
85 | end
86 |
87 | it "should be status :new for new files" do
88 | @results[0][:status].should == :new
89 | end
90 |
91 | it "should pick up the mode from the 'new file mode 160000' line" do
92 | @results[0][:mode].should == "160000"
93 | end
94 |
95 | it "should be status :deleted for deleted files" do
96 | @results[1][:status].should == :deleted
97 | end
98 |
99 | it "should pick up the mode from the 'deleted file mode 160000' line" do
100 | @results[1][:mode].should == "160000"
101 | end
102 | end
103 | end
104 |
--------------------------------------------------------------------------------
/Support/app/controllers/diff_controller.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | class DiffController < ApplicationController
4 | include SubmoduleHelper
5 | include DiffHelper
6 | def diff
7 | show_diff_title unless params[:layout].to_s=="false"
8 | @rev = params[:rev]
9 | @title = params[:title] || "Diff result"
10 | params[:context_lines] = git.config.context_lines if git.config.context_lines
11 |
12 | render("_diff_results", :locals => {
13 | :diff_check_results => git.config.show_diff_check? ? git.with_path(params[:git_path]).diff_check(params.filter(:path, :revision, :context_lines, :revisions, :branches, :tags, :since)) : [],
14 | :diff_results => git.with_path(params[:git_path]).diff(params.filter(:path, :revision, :context_lines, :revisions, :branches, :tags, :since)),
15 | :git => git.with_path(params[:git_path])
16 | })
17 | end
18 |
19 | def uncommitted_changes
20 | paths = case
21 | when params[:path]
22 | [params[:path]]
23 | else
24 | git.paths
25 | end
26 | base = git.path
27 | open_in_tm_link
28 | puts "Uncommitted Changes for ‘#{htmlize(paths.map{|path| shorten(path, base)} * ', ')}’ on branch ‘#{git.branch.current_name}’ "
29 |
30 | paths.each do |path|
31 | render("_diff_results", :locals => {
32 | :diff_check_results => git.config.show_diff_check? ? git.diff_check(:path => path, :since => "HEAD") : [],
33 | :diff_results => git.diff(:path => path, :since => "HEAD")
34 | })
35 |
36 | git.submodule.all(:path => path).each do |submodule|
37 | next if (diff_results = submodule.git.diff(:since => "HEAD")).blank?
38 | render_submodule_header(submodule)
39 | render("_diff_results", :locals => {:git => submodule.git, :diff_results => diff_results, :diff_check_results => git.config.show_diff_check? ? git.diff_check(:path => path, :since => "HEAD") : []})
40 | end
41 | end
42 | end
43 |
44 | def compare_revisions
45 | file_paths = git.paths
46 | if file_paths.length > 1
47 | base = git.nca(file_paths)
48 | else
49 | base = file_paths.first
50 | end
51 |
52 | log = LogController.new
53 | revisions = log.choose_revision(base, "Choose revisions for #{file_paths.map{|f| git.make_local_path(f)}.join(',')}", :multiple, :sort => true)
54 |
55 | if revisions.nil?
56 | puts "Canceled"
57 | return
58 | end
59 |
60 | render_component(:controller => "diff", :action => "diff", :revisions => revisions, :path => base)
61 | end
62 |
63 | protected
64 | def open_in_tm_link
65 | tmp_file = "#{ENV['TMPDIR']}/output.diff"
66 | File.unlink(tmp_file) if File.exist? tmp_file
67 | puts <<-EOF
68 | Open diff in TextMate
69 | EOF
70 | end
71 |
72 | def show_diff_title
73 | puts ""
74 | case
75 | when params[:branches]
76 | branches = params[:branches]
77 | branches = branches.split("..") if params[:branches].is_a?(String)
78 | puts "Comparing branches #{branches.first}..#{branches.last}"
79 | when params[:revisions]
80 | revisions = params[:revisions]
81 | revisions = revisions.split("..") if params[:revisions].is_a?(String)
82 | puts "Comparing branches #{revisions.first}..#{revisions.last}"
83 | end
84 | puts " "
85 | end
86 |
87 | def extract_diff_params(params)
88 | diff_params = params.dup.delete_if do |key, value|
89 | ! [:revisions, :revision, :branches, :tags, :path].include?(key)
90 | end
91 | diff_params[:context_lines] = git.config["git-tmbundle.log.context-lines"] if git.config["git-tmbundle.log.context-lines"]
92 | diff_params
93 | end
94 | end
95 |
--------------------------------------------------------------------------------
/Support/lib/commands/submodule.rb:
--------------------------------------------------------------------------------
1 | require 'digest/md5'
2 | require 'fileutils'
3 |
4 | class SCM::Git::Submodule < SCM::Git::CommandProxyBase
5 | def init_and_update
6 | output = @base.command("submodule", "init")
7 | output << @base.command("submodule", "update")
8 | output
9 | end
10 |
11 | def all(options = {})
12 | list(options).map do |sm|
13 | SubmoduleProxy.new(@base, self, sm)
14 | end
15 | end
16 |
17 | def add(repository, path)
18 | path = @base.make_local_path(path)
19 | @base.popen_command("submodule", "add", "--", repository, path)
20 | end
21 |
22 | protected
23 | def list(options = {})
24 | args = ["ls-files", "--stage"]
25 | args << options[:path] if options[:path]
26 | @base.command(*args).split("\n").grep(/^160000 /).map do |line|
27 | next unless line.match(/^160000\s*([a-f0-9]+)\s*([0-9]+)\s*(.+)/)
28 | {
29 | :revision => $1,
30 | :path => $3
31 | }
32 | end.compact
33 | end
34 |
35 | class SubmoduleProxy
36 | attr_reader :revision, :path, :tag, :state
37 |
38 | def initialize(base, parent, options = {})
39 | @base, @parent, @tag = base, parent, tag
40 | options.each do |key, value|
41 | instance_variable_set("@#{key}", value)
42 | end
43 | end
44 |
45 | def url
46 | @url ||= @base.config[:local, "submodule.#{path}.url"]
47 | end
48 |
49 | def name
50 | path
51 | end
52 |
53 | def abs_cache_path
54 | @abs_cache_path ||= File.join(@base.path, ".git/submodule_cache", Digest::MD5.hexdigest("#{path} #{url}"))
55 | end
56 |
57 | def abs_path
58 | @abs_path ||= File.join(@base.path, @path)
59 | end
60 |
61 | def cache
62 | if cloned?
63 | if File.exist?(abs_cache_path)
64 | puts "Cowardly refusing to overwrite cached submodule in #{abs_cache_path} (please look at the contents of that folder, move it out of the way, then try again)"
65 | abort
66 | end
67 |
68 | FileUtils.mkdir_p(File.dirname(abs_cache_path))
69 | FileUtils.mv(abs_path, abs_cache_path, :force => true)
70 | true
71 | end
72 | end
73 |
74 | def restore
75 | return false if Dir.has_a_file?(abs_path)
76 | if cached?
77 | FileUtils.rm_rf(abs_path)
78 | FileUtils.mkdir_p(File.dirname(abs_path))
79 | FileUtils.mv(abs_cache_path, abs_path, :force => true)
80 | end
81 | true
82 | end
83 |
84 | def git
85 | @git ||= @base.with_path(abs_path)
86 | end
87 |
88 | def current_revision(reload = false)
89 | @current_revision = nil if reload
90 | @current_revision ||= git.current_revision
91 | end
92 |
93 | def current_revision_description
94 | @current_revision_description ||= git.describe(current_revision)
95 | end
96 |
97 | def revision_description
98 | @revision_description ||= git.describe(revision)
99 | end
100 |
101 | def modified?
102 | return false unless cloned?
103 | current_revision != revision
104 | end
105 |
106 | def cloned?
107 | File.exist?(File.join(abs_path, ".git")) || cached?
108 | end
109 |
110 | def cached?
111 | File.exist?(abs_cache_path)
112 | end
113 |
114 | def update
115 | @base.command("submodule", "update", path)
116 | end
117 |
118 | def init
119 | @base.command("submodule", "init", path)
120 | end
121 | end
122 | end
123 |
124 | class Dir
125 | def self.has_a_file?(abs_path)
126 | Dir[abs_path + "/**/*"].any? {|f| File.file?(f) }
127 | end
128 | end
--------------------------------------------------------------------------------
/Support/spec/lib/commands/push_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../spec_helper'
2 |
3 | require 'stringio'
4 |
5 | describe Git do
6 | include SpecHelpers
7 |
8 | before(:each) do
9 | @push = Git.new
10 | @push.version = "1.5.3"
11 | end
12 |
13 | describe "standard push" do
14 | before(:each) do
15 | @process_io = StringIO.new <<-EOF
16 | updating 'refs/heads/mybranch'
17 | from f0f27c95b7cdf4ca3b56ecb3c54ef3364133eb6a
18 | to d8b368361ebdf2c51b78f7cfdae5c3044b23d189
19 | Also local refs/remotes/satellite/mybranch
20 | updating 'refs/heads/satellite'
21 | from 60a254470cd97af3668ed4d6405633af850139c6
22 | to 746fba2424e6b94570fc395c472805625ab2ed25
23 | Also local refs/remotes/satellite/satellite
24 | Generating pack...
25 | Done counting 6 objects.
26 | Deltifying 6 objects...
27 | 16% (1/6) done\r 33% (2/6) done\r 50% (3/6) done\r 66% (4/6) done\r 83% (5/6) def done(args)
28 |
29 | end
30 | \r 100% (6/6) done\n
31 | Writing 6 objects...
32 | 16% (1/6) done\r 33% (2/6) done\r 50% (3/6) done\r 66% (4/6) done\r 83% (5/6) done\r 100% (6/6) done\n
33 | Total 6 (delta 1), reused 0 (delta 0)
34 | refs/heads/satellite: 60a254470cd97af3668ed4d6405633af850139c6 -> 746fba2424e6b94570fc395c472805625ab2ed25
35 | refs/heads/mybranch: f0f27c95b7cdf4ca3b56ecb3c54ef3364133eb6a -> d8b368361ebdf2c51b78f7cfdae5c3044b23d189
36 | EOF
37 | end
38 |
39 | it "should call the status proc 6 times" do
40 | started_count = {}
41 | finished = {}
42 | output = {"Deltifying" => [], "Writing" => [] }
43 | @push.process_push(@process_io,
44 | :start => lambda { |state, count| started_count[state] = count },
45 | :progress => lambda {|state, percent, index, count| state; output[state] << [percent, index, count]},
46 | :end => lambda { |state, count| finished[state] = true }
47 | )
48 |
49 | for state in ["Deltifying", "Writing"]
50 | started_count[state].should == 6
51 | output[state].map{|o| o[0]}.should == [0,16,33,50,66,83,100]
52 | output[state].map{|o| o[1]}.should == (0..6).to_a
53 | output[state].map{|o| o[2]}.should == [6] * 7
54 | finished[state].should == true
55 | end
56 | end
57 |
58 | it "should return a list of all revisions pushed" do
59 | output = @push.process_push(@process_io)
60 | output[:pushes].should == {
61 | "refs/heads/satellite" => ["60a254470cd97af3668ed4d6405633af850139c6", "746fba2424e6b94570fc395c472805625ab2ed25"],
62 | "refs/heads/mybranch" => ["f0f27c95b7cdf4ca3b56ecb3c54ef3364133eb6a", "d8b368361ebdf2c51b78f7cfdae5c3044b23d189"]
63 | }
64 | end
65 |
66 | it "should return :nothing_to_push if Everything up-to-date" do
67 | output = @push.process_push(StringIO.new("Everything up-to-date\n"))
68 | output[:nothing_to_push].should == true
69 | end
70 | end
71 |
72 | describe "for git 1.5.4.3" do
73 | before(:each) do
74 | @process_io = StringIO.new(fixture_file("push_1_5_4_3_output.txt"))
75 | @push.version = "1.5.4.3"
76 | end
77 |
78 | it "should call the progress proc 6 times for state Compressing" do
79 | output = {"Compressing" => [], "Writing" => [] }
80 |
81 | @push.process_push(@process_io, :progress => lambda {|state, percent, index, count| output[state] << [percent, index, count]})
82 | output["Compressing"].map{|o| o[0]}.should == [50,100]
83 | output["Compressing"].map{|o| o[1]}.should == [1,2]
84 | output["Compressing"].map{|o| o[2]}.should == [2,2]
85 | output["Writing"].map{|o| o[0]}.should == [33,66,100]
86 | output["Writing"].map{|o| o[1]}.should == [1,2,3]
87 | output["Writing"].map{|o| o[2]}.should == [3,3,3]
88 | end
89 |
90 | it "should extract the push information for the branch and assume the current branch" do
91 | output = @push.process_push(@process_io)
92 |
93 | output[:pushes]['asdf'].should == ["865f920", "f9ca10d"]
94 | output[:pushes]['master'].should == nil
95 |
96 | end
97 | end
98 | end
99 |
--------------------------------------------------------------------------------
/Support/app/controllers/stash_controller.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require ENV['TM_SUPPORT_PATH'] + '/lib/ui.rb'
3 |
4 | class StashController < ApplicationController
5 | include DiffHelper
6 |
7 | layout "application", :except => ["clear"]
8 | def show
9 | if git.stash.list.empty?
10 | puts "Stash list is empty"
11 | end
12 |
13 | stash_item = select_stash
14 |
15 | if stash_item.nil?
16 | puts "Aborted"
17 | return
18 | end
19 |
20 | puts "Diff for stash ‘#{stash_item[:description]}’ "
21 | render("diff/_diff_results", :locals => {:diff_results => (git.stash.diff(stash_item[:name]))})
22 | end
23 |
24 | def pop
25 | stash_item = select_stash(:prompt => "Select a stash to pop")
26 | if stash_item.nil?
27 | puts "Cancelled"
28 | return
29 | end
30 | puts "Popping stash '#{stash_item[:description]}' "
31 | flush
32 |
33 | stash_diff = git.stash.diff(stash_item[:name])
34 |
35 | stash_it = lambda {
36 | git.stash.pop(stash_item[:name])
37 | }
38 |
39 | result = stash_it.call
40 |
41 | if result.match(/Cannot restore on top of a dirty state/)
42 | response = TextMate::UI.alert(:warning, "You're not on a clean working copy", "You may want to commit your outstanding changes before stashing.\nWould you like to apply your stash anyways? (could cause conflicts)", "No", "Yes")
43 | if response == "Yes"
44 | git.command("add", ".")
45 | result = stash_it.call
46 | git.command("reset")
47 | else
48 | return
49 | end
50 | end
51 |
52 | status_data = git.parse_status(result)
53 | if status_data.empty?
54 | puts "I didn't understand git's response. Perhaps you can?"
55 | puts "#{result} "
56 | return
57 | end
58 |
59 | puts "Successfully applied "
60 | puts "Project Status: "
61 | render "status/_status", :locals => {:status_data => status_data}
62 |
63 | puts "Diff of stash applied: "
64 | render("/diff/_diff_results", :locals => {:diff_results => stash_diff})
65 | end
66 |
67 | def save
68 | untracked_files = git.list_files(git.path, :type => "o")
69 | if untracked_files.length >= 1
70 | response = TextMate::UI.alert(:warning, "Untracked files in working copy", "Would you like to include the following untracked files in your stash?:\n#{untracked_files * "\n"}\n", "Add them", "Leave them out", "Cancel")
71 | case response
72 | when "Add them"
73 | git.command("add", ".")
74 | when "Cancel", nil
75 | return exit_discard
76 | end
77 | end
78 |
79 | stash_description = TextMate::UI.request_string(:title => "Stash", :prompt => "Describe stash:", :default => "WIP: ")
80 | if stash_description.nil?
81 | return exit_discard
82 | end
83 | stash_description = "WIP" if stash_description.empty?
84 |
85 | result = git.stash.save(stash_description)
86 | if result.match(/Saved working directory and index state/)
87 |
88 | end
89 | puts result
90 | end
91 |
92 | def clear
93 | if git.stash.list.empty?
94 | puts "No stashes for current branch (#{git.branch.current_name})"
95 | return
96 | end
97 |
98 | stash_text_list = git.stash.list.map{|s| "#{s[:id]} - #{s[:description]}"} * "\n"
99 | response = TextMate::UI.alert(:warning, "Clear all stashes?", "Do you really want to clear the following stashes? \n#{stash_text_list}", 'Yes', 'Cancel')
100 | if response == 'Yes'
101 | git.stash.clear
102 | puts "Stash cleared"
103 | else
104 | puts "Cancelled"
105 | end
106 | end
107 |
108 | protected
109 | def select_stash(options={})
110 | options = {:title => "Select stash", :prompt => "Select a stash", :items => git.stash.list.map{|s| "#{s[:id]} - #{s[:description]}"}}.merge(options)
111 | TextMate::UI.request_item(options) do |stash_id|
112 | selected_stash_entry = git.stash.list.find { |s| s[:id].to_i == stash_id.to_i }
113 | return selected_stash_entry
114 | end
115 | nil
116 | end
117 | end
--------------------------------------------------------------------------------
/Support/lib/partial_commit_worker.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | module PartialCommitWorker
4 | class NotOnBranchException < Exception; end
5 | class NothingToCommitException < Exception; end
6 | class NothingToAmendException < Exception; end
7 | class CommitCanceledException < Exception; end
8 |
9 | def self.factory(_type, *args)
10 | klass = (_type == "amend" ? PartialCommitWorker::Amend : PartialCommitWorker::Normal)
11 | klass.new(*args)
12 | end
13 |
14 | class Base
15 | COMMIT_CONTINUE = 'TM_SCM_COMMIT_CONTINUE=1'
16 | attr_reader :git
17 |
18 | def initialize(git)
19 | @git = git
20 | @base = git.path
21 | end
22 |
23 | def ok_to_proceed_with_partial_commit?
24 | git.rebase_in_progress? || (! git.branch.current_name.nil?) || git.initial_commit_pending?
25 | end
26 |
27 | def target_paths
28 | @target_paths ||= git.paths
29 | end
30 |
31 | def split_file_statuses
32 | [file_candidates.map{ |fc| fc[0] }, file_candidates.map{ |fc| fc[1] }]
33 | end
34 |
35 | def status_helper_tool
36 | ENV['TM_BUNDLE_SUPPORT'] + '/gateway/commit_dialog_helper.rb'
37 | end
38 |
39 | def tm_scm_commit_window
40 | files, statuses = split_file_statuses
41 |
42 | res = ""
43 | res << "cd \"#{git.path}\" && \"$TM_SCM_COMMIT_WINDOW\""
44 | res << " --log #{Shellwords.escape(git.log(:limit => 1).first[:msg])}" if amend?
45 | res << " --diff-cmd '#{git.git},diff,HEAD,--'"
46 | res << " --action-cmd 'M,D:${TM_DISPLAYNAME:?Revert “${TM_DISPLAYNAME}”:Revert},#{status_helper_tool},revert'"
47 | res << " --action-cmd '?:${TM_DISPLAYNAME:?Delete “${TM_DISPLAYNAME}”:Delete},#{status_helper_tool},delete'"
48 | res << " --status #{statuses.join(':')}" if !amend? || (amend? && !file_candidates.empty?)
49 | res << " --show-continue-button" if git.rebase_in_progress?
50 | res << " --commit-button-title Amend" if amend?
51 | res << " #{files.map{ |f| e_sh(f) }.join(' ')} 2>/dev/console"
52 |
53 | res
54 | end
55 |
56 | def exec_commit_dialog
57 | res = %x{#{tm_scm_commit_window}}
58 | res = Shellwords.shellwords(res)
59 |
60 | continue = res.last == COMMIT_CONTINUE
61 | res = res[0 ... -1] if continue
62 |
63 | canceled = ($? != 0)
64 | msg = res[1]
65 | files = res[2..-1]
66 | return canceled, msg, files, continue
67 | end
68 |
69 | def show_commit_dialog
70 | canceled, msg, files, continue = exec_commit_dialog
71 | raise CommitCanceledException if canceled
72 | [msg, files, continue]
73 | end
74 |
75 | def file_candidates
76 | @file_candidates ||=
77 | git.status(target_paths).map do |e|
78 | [shorten(e[:path], @base), e[:status][:short]]
79 | end
80 | end
81 |
82 | def run
83 | raise NotOnBranchException unless ok_to_proceed_with_partial_commit?
84 | raise NothingToCommitException if nothing_to_commit?
85 |
86 | if amend?
87 | raise NothingToAmendException if nothing_to_amend?
88 | end
89 |
90 | msg, files, continue = show_commit_dialog
91 | git.auto_add_rm(files)
92 | res = git.commit(msg, files, :amend => amend?)
93 | git.command('rebase', '--continue') if continue
94 | { :files => files, :message => msg, :result => res}
95 | end
96 |
97 | def title
98 | "#{title_prefix} in #{target_paths.map { |e| htmlize("‘" + shorten(e, ENV['TM_PROJECT_DIRECTORY'] || @base) + "’") } * ', '} on branch ‘#{htmlize(git.branch.current_name)}’"
99 | end
100 |
101 | def nothing_to_commit?
102 | amend? ? false : file_candidates.empty?
103 | end
104 |
105 | def nothing_to_amend?
106 | git.initial_commit_pending?
107 | end
108 | end
109 |
110 | class Normal < Base
111 | def title_prefix
112 | "Committing Files"
113 | end
114 |
115 | def amend?
116 | false
117 | end
118 | end
119 |
120 | class Amend < Base
121 |
122 | def title_prefix
123 | "Amending the commit"
124 | end
125 |
126 | def amend?
127 | true
128 | end
129 |
130 | def show_commit_dialog(*args)
131 | msg, files, continue = super(*args)
132 | [msg, files, continue]
133 | end
134 |
135 | def file_candidates
136 | return @file_candidates if @file_candidates
137 | super
138 | @file_candidates
139 | end
140 | end
141 | end
142 |
--------------------------------------------------------------------------------