19 | <% end %>
20 | <% if @submodules.empty? %>
21 |
22 |
No submodules defined.
23 |
24 | <% end %>
25 |
26 |
--------------------------------------------------------------------------------
/Support/dispatch.rb:
--------------------------------------------------------------------------------
1 | $dispatch_loaded = true
2 | require File.dirname(__FILE__) + "/environment.rb"
3 |
4 | dispatch(ARGV) if $0 == __FILE__ && ! $dispatched
5 |
--------------------------------------------------------------------------------
/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/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/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
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/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/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/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/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/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/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
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/nibs/CompareBranches.nib/keyedobjects.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/textmate/git.tmbundle/50e22e79ab3c8874f38fefef8cc6e7da0d0b3bcd/Support/nibs/CompareBranches.nib/keyedobjects.nib
--------------------------------------------------------------------------------
/Support/nibs/RevisionSelector.nib/keyedobjects.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/textmate/git.tmbundle/50e22e79ab3c8874f38fefef8cc6e7da0d0b3bcd/Support/nibs/RevisionSelector.nib/keyedobjects.nib
--------------------------------------------------------------------------------
/Support/resource/git-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/textmate/git.tmbundle/50e22e79ab3c8874f38fefef8cc6e7da0d0b3bcd/Support/resource/git-logo.png
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/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/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
--------------------------------------------------------------------------------
/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/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/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/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/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/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/spec/fixtures/commit_result.txt:
--------------------------------------------------------------------------------
1 | Created commit 24ff719: work done
2 | 1 files changed, 1 insertions(+), 0 deletions(-)
3 |
--------------------------------------------------------------------------------
/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/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/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/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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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/stash_list_response_many_stashes.txt:
--------------------------------------------------------------------------------
1 | stash@{0}: On master: boogy
2 | stash@{1}: On master: oogity
3 |
--------------------------------------------------------------------------------
/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/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/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/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/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/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/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/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/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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/spec/run_all_spec.rb:
--------------------------------------------------------------------------------
1 | Dir.glob(File.dirname(__FILE__) + "/**/*_spec.rb").each do |file|
2 | require file
3 | end
--------------------------------------------------------------------------------
/Support/spec/spec.opts:
--------------------------------------------------------------------------------
1 | --color
2 | --reverse
3 |
--------------------------------------------------------------------------------
/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/tmvc/lib/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | include HtmlHelpers
3 | end
4 |
--------------------------------------------------------------------------------
/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/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/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/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 |
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 << ""
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/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/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/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/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/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/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/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/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/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
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------