git-si 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,153 @@
1
+ require "git/si/errors"
2
+
3
+ module Git
4
+
5
+ module Si
6
+
7
+ module Actions
8
+
9
+ def do_status_action( args=[] )
10
+ on_local_branch do
11
+ return if do_revisions_differ()
12
+ svn_status = get_command_output( Git::Si::SvnControl.status_command( args ) )
13
+ print_colordiff Git::Si::SvnControl.parse_svn_status( svn_status ).join( "\n" )
14
+ end
15
+ end
16
+
17
+ def do_diff_action( args=[] )
18
+ on_local_branch do
19
+ return if do_revisions_differ()
20
+
21
+ notice_message "Adding any files that are not already in svn to ensure an accurate diff."
22
+ do_readd_action
23
+
24
+ print_colordiff get_command_output( Git::Si::SvnControl.diff_command( args ) )
25
+ end
26
+ end
27
+
28
+ def do_add_action( args=[] )
29
+ on_local_branch do
30
+ run_command( Git::Si::SvnControl.add_command( args ) )
31
+ run_command( Git::Si::GitControl.add_command( args ) )
32
+ end
33
+ end
34
+
35
+ def do_readd_action
36
+ on_local_branch do
37
+ files_to_add = []
38
+ Git::Si::SvnControl.parse_unknown_files( get_command_output( Git::Si::SvnControl.status_command ) ).each do |filename|
39
+ if is_file_in_git?( filename )
40
+ files_to_add << filename if filename != '.gitignore'
41
+ end
42
+ end
43
+
44
+ if files_to_add.empty?
45
+ notice_message "There are no files to add."
46
+ return
47
+ end
48
+
49
+ using_stderr do
50
+ files_to_add.each do |filename|
51
+ say filename
52
+ end
53
+ if yes? "Do you want to add the above files to svn? [y/N] ", :green
54
+ run_command( Git::Si::SvnControl.add_command( files_to_add ) )
55
+ success_message "Added files to svn that had been added to git."
56
+ end
57
+ end
58
+
59
+ end
60
+ end
61
+
62
+ def do_fetch_action
63
+ stashed_changes = stash_local_changes
64
+ on_mirror_branch do
65
+ notice_message "Fetching remote data from svn"
66
+ updated_files = get_command_output( Git::Si::SvnControl.update_command )
67
+ revert_files_to_svn_update( updated_files )
68
+ delete_files_after_svn_update( updated_files )
69
+ add_files_after_svn_update( updated_files )
70
+ run_command( Git::Si::GitControl.commit_revision_command( get_svn_revision ) )
71
+ end
72
+ unstash_local_changes( stashed_changes )
73
+ success_message "fetch complete!"
74
+ end
75
+
76
+ def do_rebase_action
77
+ on_local_branch do
78
+ stashed_changes = stash_local_changes
79
+ run_command( Git::Si::GitControl.rebase_command( get_mirror_branch ) )
80
+ unstash_local_changes( stashed_changes )
81
+ success_message "rebase complete!"
82
+ end
83
+ end
84
+
85
+ def do_pull_action
86
+ do_fetch_action
87
+ do_rebase_action
88
+ end
89
+
90
+ def do_commit_action
91
+ local_branch = get_local_branch()
92
+ if local_branch == 'master'
93
+ error_message "Please do not commit changes on the master branch"
94
+ return
95
+ end
96
+
97
+ on_local_branch do
98
+ raise Git::Si::GitError.new("There are local changes; please commit them before continuing.") if are_there_git_changes?
99
+
100
+ notice_message "Adding any files that are not already in svn to ensure changes are committed."
101
+ do_readd_action
102
+
103
+ svn_diff = get_command_output( Git::Si::SvnControl.diff_command )
104
+ raise Git::Si::SvnError.new("There are no changes to commit.") if svn_diff.strip.empty?
105
+
106
+ run_command( Git::Si::SvnControl.commit_command )
107
+ success_message "commit complete!"
108
+
109
+ if are_there_git_changes? and yes?( "Some files were added or modified during the commit; should I revert them? [y/N] ", :yellow )
110
+ run_command( Git::Si::GitControl.hard_reset_command )
111
+ end
112
+ end
113
+
114
+ notice_message "Updating mirror branch to latest commit"
115
+ do_fetch_action
116
+
117
+ delete_committed_branch( local_branch ) if yes?( "Do you want to switch to the master branch and delete the committed branch '#{local_branch}'? [y/N] ", :green )
118
+ end
119
+
120
+ def do_init_action
121
+ on_local_branch do
122
+ # check for svn repo
123
+ run_command( Git::Si::SvnControl.info_command, { :allow_errors => true } )
124
+ raise Git::Si::SvnError.new("No svn repository was found here. Maybe you're in the wrong directory?") unless did_last_command_succeed?
125
+
126
+ # make sure svn repo is up-to-date
127
+ run_command( Git::Si::SvnControl.update_command )
128
+
129
+ make_a_commit = false
130
+
131
+ # check for existing .git repo
132
+ make_a_commit = true if create_git_repository()
133
+
134
+ # check for existing .gitignore
135
+ make_a_commit = true if create_gitignore()
136
+
137
+ # make initial commit
138
+ if make_a_commit
139
+ notice_message "Making initial commit."
140
+ run_command( Git::Si::GitControl.commit_revision_command(get_svn_revision) )
141
+ end
142
+
143
+ # check for exiting mirror branch
144
+ create_mirror_branch()
145
+
146
+ success_message "init complete!"
147
+ end
148
+ end
149
+
150
+ end
151
+ end
152
+ end
153
+
@@ -0,0 +1,20 @@
1
+ module Git
2
+ module Si
3
+
4
+ class GitSiError < StandardError
5
+ end
6
+
7
+ class ShellError < GitSiError
8
+ end
9
+
10
+ class GitError < GitSiError
11
+ end
12
+
13
+ class SvnError < GitSiError
14
+ end
15
+
16
+ class VersionError < GitSiError
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,112 @@
1
+ require "git/si/version"
2
+
3
+ module Git
4
+ module Si
5
+ class GitControl
6
+ @@default_git_binary = 'git'
7
+ @@git_binary = 'git'
8
+
9
+ def self.git_binary=(binary)
10
+ @@git_binary = binary && binary.length > 0 ? binary : @@default_git_binary
11
+ end
12
+
13
+ def self.status_command(*args)
14
+ command = "#{@@git_binary} status --porcelain"
15
+ if ( args.length > 0 )
16
+ command += " " + args.join(' ')
17
+ end
18
+ command
19
+ end
20
+
21
+ def self.log_command(*args)
22
+ command = "#{@@git_binary} log"
23
+ if ( args.length > 0 )
24
+ command += " " + args.join(' ')
25
+ end
26
+ command
27
+ end
28
+
29
+ def self.parse_last_svn_revision(info)
30
+ results = info.match(/svn update to version (\d+)/i)
31
+ return results[1] if results
32
+ end
33
+
34
+ def self.add_command(*files)
35
+ raise GitSiError.new("Add command requires filenames") if ( files.length == 0 )
36
+ "#{@@git_binary} add " + files.join(' ')
37
+ end
38
+
39
+ def self.are_there_changes?(status_output)
40
+ status_output.match(/^\s*[MADRC]/)
41
+ end
42
+
43
+ def self.commit_revision_command(revision)
44
+ version = Git::Si::Version.version
45
+ "#{@@git_binary} commit --allow-empty -am 'git-si #{version} svn update to version #{revision}'"
46
+ end
47
+
48
+ def self.stash_command
49
+ "#{@@git_binary} stash"
50
+ end
51
+
52
+ def self.unstash_command
53
+ "#{@@git_binary} stash pop"
54
+ end
55
+
56
+ def self.rebase_command(branch)
57
+ raise GitSiError.new("Rebase command requires branch name") if branch.empty?
58
+ "#{@@git_binary} rebase '#{branch}'"
59
+ end
60
+
61
+ def self.checkout_command(branch)
62
+ raise GitSiError.new("Checkout command requires branch name") if branch.empty?
63
+ "#{@@git_binary} checkout #{branch}"
64
+ end
65
+
66
+ def self.create_branch_command(branch)
67
+ raise GitSiError.new("New branch command requires branch name") if branch.empty?
68
+ "#{@@git_binary} branch #{branch}"
69
+ end
70
+
71
+ def self.delete_branch_command(branch)
72
+ raise GitSiError.new("Delete branch command requires branch name") if branch.empty?
73
+ "#{@@git_binary} branch -D #{branch}"
74
+ end
75
+
76
+ def self.branch_command
77
+ "#{@@git_binary} branch"
78
+ end
79
+
80
+ def self.parse_current_branch(git_branches)
81
+ results = git_branches.match(/^\*\s+(\S+)/)
82
+ return results[1] if results
83
+ end
84
+
85
+ def self.hard_reset_command
86
+ "#{@@git_binary} reset --hard HEAD"
87
+ end
88
+
89
+ def self.list_file_command(filename)
90
+ raise GitSiError.new("List file command requires filename") if filename.empty?
91
+ "#{@@git_binary} ls-files #{filename}"
92
+ end
93
+
94
+ def self.init_command
95
+ "#{@@git_binary} init"
96
+ end
97
+
98
+ def self.show_branch_command(branch)
99
+ raise GitSiError.new("Show branch command requires branch name") if branch.empty?
100
+ "#{@@git_binary} show-ref refs/heads/#{branch}"
101
+ end
102
+
103
+ def self.delete_command(filename)
104
+ raise GitSiError.new("Remove file command requires filename") if filename.empty?
105
+ "#{@@git_binary} rm #{filename}"
106
+ end
107
+
108
+ end
109
+ end
110
+ end
111
+
112
+
@@ -0,0 +1,23 @@
1
+ module Git
2
+ module Si
3
+ class GitIgnore
4
+ @@gitignore_patterns = [".*", "!.gitignore", ".svn", "*.sw?", ".config", "*.err", "*.pid", "*.log", "svn-commit.*", "*.orig", "node_modules"]
5
+
6
+ def self.ignore_patterns
7
+ @@gitignore_patterns
8
+ end
9
+
10
+ def self.get_missing_lines_from(lines, patterns=@@gitignore_patterns)
11
+ patterns.reject do |pattern|
12
+ lines.detect do |line|
13
+ line.strip.eql? pattern.strip
14
+ end
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+
22
+
23
+
@@ -0,0 +1,135 @@
1
+ module Git
2
+ module Si
3
+ class SvnControl
4
+ @@default_svn_binary = 'svn'
5
+ @@svn_binary = 'svn'
6
+
7
+ def self.svn_binary=(binary)
8
+ @@svn_binary = binary && binary.length > 0 ? binary : @@default_svn_binary
9
+ end
10
+
11
+ def self.status_command(*args)
12
+ command = "#{@@svn_binary} status --ignore-externals"
13
+ if ( args.length > 0 )
14
+ command += " " + args.join(' ')
15
+ end
16
+ command
17
+ end
18
+
19
+ def self.info_command
20
+ "#{@@svn_binary} info"
21
+ end
22
+
23
+ def self.diff_command(*args)
24
+ command = "#{@@svn_binary} diff"
25
+ if ( args.length > 0 )
26
+ command += " " + args.join(' ')
27
+ end
28
+ command
29
+ end
30
+
31
+ def self.parse_last_revision(svn_info)
32
+ results = svn_info.match(/^Revision:\s+(\d+)/)
33
+ return results[1] if results
34
+ return nil
35
+ end
36
+
37
+ def self.parse_root_path(svn_info)
38
+ results = svn_info.match(/Root Path:\s+(.+)/)
39
+ return results[1] if results
40
+ return nil
41
+ end
42
+
43
+ def self.parse_updated_files(svn_update_output)
44
+ svn_update_output.split(/\r?\n/).collect do |line|
45
+ line.strip.match(Regexp.union(/^\s*[AGU]\s+(\S.+)/, /^Restored '(.+)'/, /^Resolved conflicted state of '(.+)'/)) do |pattern|
46
+ pattern.to_a.compact.last
47
+ end
48
+ end.compact
49
+ end
50
+
51
+ def self.parse_deleted_files(svn_update_output)
52
+ svn_update_output.split(/\r?\n/).collect do |line|
53
+ line.strip.match(Regexp.union(/^\s*D\s+(\S.+)/)) do |pattern|
54
+ pattern.to_a.compact.last
55
+ end
56
+ end.compact
57
+ end
58
+
59
+ def self.parse_conflicted_files(svn_update_output)
60
+ svn_update_output.split(/\r?\n/).collect do |line|
61
+ line.strip.match(Regexp.union(/^\s*C\s+(\S.+)/, /^Resolved conflicted state of '(.+)'/)) do |pattern|
62
+ pattern.to_a.compact.last
63
+ end
64
+ end.compact
65
+ end
66
+
67
+ def self.parse_unknown_files(svn_update_output)
68
+ svn_update_output.split(/\r?\n/).collect do |line|
69
+ line.strip.match(/^\s*\?\s+(\S.+)/) do |pattern|
70
+ pattern.to_a.compact.last
71
+ end
72
+ end.compact
73
+ end
74
+
75
+ def self.add_command(*files)
76
+ raise GitSiError.new("Add command requires filenames") if ( files.length == 0 )
77
+ "#{@@svn_binary} add " + files.join(' ')
78
+ end
79
+
80
+ def self.blame_command(*files)
81
+ raise GitSiError.new("Blame command requires filenames") if ( files.length == 0 )
82
+ "#{@@svn_binary} blame " + files.join(' ')
83
+ end
84
+
85
+ def self.update_command
86
+ "#{@@svn_binary} up --accept theirs-full --ignore-externals"
87
+ end
88
+
89
+ def self.revert_command(*args)
90
+ command = "#{@@svn_binary} revert -R"
91
+ if ( args.length > 0 )
92
+ command += " " + args.join(' ')
93
+ else
94
+ command += " ."
95
+ end
96
+ command
97
+ end
98
+
99
+ def self.commit_command(*args)
100
+ command = "#{@@svn_binary} commit"
101
+ if ( args.length > 0 )
102
+ command += " " + args.join(' ')
103
+ end
104
+ command
105
+ end
106
+
107
+ def self.list_file_command
108
+ "#{@@svn_binary} list -R"
109
+ end
110
+
111
+ def self.parse_file_list(list_output)
112
+ list_output.split(/\r?\n/).collect do |filename|
113
+ filename.strip if filename.strip !~ Regexp.union( /\/$/, /^\./, /\/\./ ) and not filename.empty?
114
+ end.compact
115
+ end
116
+
117
+ def self.parse_svn_status(status_string)
118
+ return '' unless status_string
119
+ status_string.split(/\r?\n/).select do |line|
120
+ line.strip !~ /(^X|\.git|\.swp$)/
121
+ end
122
+ end
123
+
124
+ def self.parse_external_repos(status_string)
125
+ status_string.split(/\r?\n/).collect do |line|
126
+ line.strip.match(/^\s*X\s+(\S.+)/) do |pattern|
127
+ pattern.to_a.compact.last
128
+ end
129
+ end.compact
130
+ end
131
+
132
+ end
133
+ end
134
+ end
135
+