vcs 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/NEWS +112 -0
- data/NEWS.FR +90 -0
- data/SPEC.dyn.yml +5 -5
- data/SPEC.gemspec +4 -4
- data/SPEC.yml +5 -1
- data/bin/vcs +6 -161
- data/bin/vcs-cvs +6 -7
- data/bin/vcs-prcs +6 -7
- data/bin/vcs-svn +6 -7
- data/lib/vcs/add.rb +21 -0
- data/lib/vcs/app.rb +129 -0
- data/lib/vcs/back.rb +36 -0
- data/lib/vcs/changelog.rb +68 -123
- data/lib/vcs/common_commit.rb +110 -0
- data/lib/vcs/conflict.rb +9 -3
- data/lib/vcs/cvs.rb +4 -7
- data/lib/vcs/delete.rb +21 -0
- data/lib/vcs/diff.rb +29 -9
- data/lib/vcs/diffstat.rb +3 -3
- data/lib/vcs/edit.rb +4 -5
- data/lib/vcs/environment.rb +59 -0
- data/lib/vcs/form.rb +97 -0
- data/lib/vcs/ignore.rb +26 -0
- data/lib/vcs/junk.rb +26 -0
- data/lib/vcs/last_changed_date.rb +7 -9
- data/lib/vcs/list.rb +71 -0
- data/lib/vcs/mail.rb +25 -20
- data/lib/vcs/message.rb +32 -62
- data/lib/vcs/news.rb +9 -10
- data/lib/vcs/opt_parse.rb +82 -0
- data/lib/vcs/revision.rb +1 -1
- data/lib/vcs/script.rb +12 -6
- data/lib/vcs/status.rb +77 -5
- data/lib/vcs/svn.rb +53 -13
- data/lib/vcs/url.rb +4 -8
- data/lib/vcs/vcs.rb +443 -58
- metadata +16 -7
- data/lib/vcs/mycommit.rb +0 -90
data/bin/vcs-prcs
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# Author
|
3
|
-
# Copyright
|
4
|
-
# License
|
2
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
3
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
4
|
+
# License:: GNU General Public License (GPL).
|
5
|
+
# Revision:: $Id$
|
5
6
|
|
6
|
-
|
7
|
-
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'vcs', 'app') unless defined? VcsApp
|
8
8
|
|
9
|
-
|
10
|
-
exec('vcs', '--vcs', VCS, '--', *ARGV)
|
9
|
+
VcsApp.new(__FILE__, :prcs).run
|
data/bin/vcs-svn
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# Author
|
3
|
-
# Copyright
|
4
|
-
# License
|
2
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
3
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
4
|
+
# License:: GNU General Public License (GPL).
|
5
|
+
# Revision:: $Id$
|
5
6
|
|
6
|
-
|
7
|
-
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'vcs', 'app') unless defined? VcsApp
|
8
8
|
|
9
|
-
|
10
|
-
exec('vcs', '--vcs', VCS, '--', *ARGV)
|
9
|
+
VcsApp.new(__FILE__, :svn).run
|
data/lib/vcs/add.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Copyright:: Copyright (c) 2005 LRDE. All rights reserved.
|
2
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
3
|
+
# License:: Gnu General Public License.
|
4
|
+
# Revision:: $Id: add.rb 265 2005-10-03 12:37:03Z pouill_n $
|
5
|
+
|
6
|
+
class Vcs
|
7
|
+
|
8
|
+
specific_options << '--auto'
|
9
|
+
|
10
|
+
def add! ( files=[], options={} )
|
11
|
+
if options[:auto]
|
12
|
+
options.delete(:auto)
|
13
|
+
list!(files, :unrecognize => true) do |path_list|
|
14
|
+
add_!(path_list.stringify, options) unless path_list.empty?
|
15
|
+
end
|
16
|
+
else
|
17
|
+
add_!(files, options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end # class Vcs
|
data/lib/vcs/app.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
# Copyright:: Copyright (c) 2005 LRDE. All rights reserved.
|
2
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
3
|
+
# License:: Gnu General Public License.
|
4
|
+
# Revision:: $Id: app.rb 261 2005-10-03 00:45:53Z pouill_n $
|
5
|
+
|
6
|
+
require 'pathname'
|
7
|
+
|
8
|
+
# vcs: The version control system wrapper.
|
9
|
+
#
|
10
|
+
# Vcs is a wrapper over any version control system.
|
11
|
+
class VcsApp
|
12
|
+
|
13
|
+
@@vcs_dir ||= Pathname.new(__FILE__).expand_path.dirname
|
14
|
+
@@dir ||= @@vcs_dir.parent
|
15
|
+
@@extension_dirs ||= []
|
16
|
+
|
17
|
+
require @@vcs_dir + 'vcs' unless defined? Vcs
|
18
|
+
|
19
|
+
@@dir.load_path!
|
20
|
+
|
21
|
+
cattr_accessor :vcs_dir
|
22
|
+
cattr_accessor :dir
|
23
|
+
cattr_accessor :extension_dirs
|
24
|
+
cattr_accessor :path
|
25
|
+
cattr_accessor :logger
|
26
|
+
self.logger = Vcs.logger
|
27
|
+
|
28
|
+
class << self
|
29
|
+
|
30
|
+
def requirements
|
31
|
+
Pathname.glob("{#{vcs_dir},#{extension_dirs.join(',')}}/*.rb") do |file|
|
32
|
+
next if file.to_s =~ /\/(app|opt_parse|vcs)\.rb$/
|
33
|
+
logger.debug { file.basename.to_s } if require file.to_s
|
34
|
+
end
|
35
|
+
grab_all_vcs()
|
36
|
+
end
|
37
|
+
|
38
|
+
def grab_all_vcs
|
39
|
+
@@all_vcs ||= {}
|
40
|
+
|
41
|
+
if @@all_vcs.empty?
|
42
|
+
ObjectSpace.each_object(Class) do |aClass|
|
43
|
+
if aClass != Vcs and aClass.ancestors.include? Vcs
|
44
|
+
name = aClass.to_s.demodulize.underscore.to_sym
|
45
|
+
@@all_vcs[name] = aClass
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def all_vcs
|
52
|
+
@@all_vcs.keys
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
requirements()
|
58
|
+
require 'vcs/opt_parse'
|
59
|
+
@@parser = Vcs::OptParse.new
|
60
|
+
|
61
|
+
def initialize ( __file__, vcs_type=nil )
|
62
|
+
@@path = __file__.to_path
|
63
|
+
Vcs.default ||= vcs_type
|
64
|
+
end
|
65
|
+
|
66
|
+
def grab_dirs ( basename, dir=Pathname.pwd )
|
67
|
+
results = []
|
68
|
+
while not dir.root?
|
69
|
+
path = dir + basename
|
70
|
+
results << path if path.exist?
|
71
|
+
dir = dir.parent
|
72
|
+
end
|
73
|
+
path = ENV['HOME'].to_path/basename
|
74
|
+
results << path if path.exist? and not results.include? path
|
75
|
+
results
|
76
|
+
end
|
77
|
+
|
78
|
+
def vcs_extensions_setup
|
79
|
+
grab_dirs('vcs').each do |vcs_dir|
|
80
|
+
vcs_dir = vcs_dir.expand_path
|
81
|
+
vcs_dir.load_path!
|
82
|
+
extension_dirs << vcs_dir
|
83
|
+
end
|
84
|
+
VcsApp.requirements()
|
85
|
+
end
|
86
|
+
|
87
|
+
def user_configuration_setup
|
88
|
+
grab_dirs('.vcs').each do |vcs_user_conf|
|
89
|
+
Vcs.merge_user_conf(vcs_user_conf)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def run
|
94
|
+
vcs = nil
|
95
|
+
begin
|
96
|
+
user_configuration_setup()
|
97
|
+
Vcs.logger.color = Vcs.color? { STDERR.tty? }
|
98
|
+
vcs_extensions_setup()
|
99
|
+
@@parser.parse! ARGV if Vcs.default.nil?
|
100
|
+
if Vcs.default.nil?
|
101
|
+
STDERR.puts @@parser
|
102
|
+
STDERR.puts "
|
103
|
+
|
|
104
|
+
|Specify at least a Vcs type, or use a wrapped command
|
105
|
+
|like svn, cvs, prcs in the vcs bin directory.
|
106
|
+
".head_cut!
|
107
|
+
exit
|
108
|
+
end
|
109
|
+
vcs = @@all_vcs[Vcs.default.to_s.downcase.to_sym].new
|
110
|
+
vcs.run_argv(ARGV)
|
111
|
+
|
112
|
+
rescue SystemExit => ex
|
113
|
+
raise ex
|
114
|
+
rescue Exception => ex
|
115
|
+
if vcs.nil?
|
116
|
+
logger.error { "No Vcs instanciated" }
|
117
|
+
else
|
118
|
+
vcs.call_handlers
|
119
|
+
end
|
120
|
+
err = ex.to_s.sub(/\.$/, '')
|
121
|
+
logger.debug { err = ex.long_pp ; "Backtrace enabled:" }
|
122
|
+
err = ex.inspect if err.empty?
|
123
|
+
logger.error { err }
|
124
|
+
exit 1
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
end # class VcsApp
|
129
|
+
|
data/lib/vcs/back.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright:: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
|
2
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
3
|
+
# License:: Gnu General Public License.
|
4
|
+
# Revision:: $Id: back.rb 261 2005-10-03 00:45:53Z pouill_n $
|
5
|
+
|
6
|
+
class Vcs
|
7
|
+
# This command take a command as argument and search the last revision where
|
8
|
+
# this command success.
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
# * this dummy example success only if the revision is equal to 0 modulo X
|
12
|
+
# * replace X by the success revision and Y by a greater revision
|
13
|
+
# vcs-svn back -r Y vcs-svn script 'exit(rev.read.to_i % X)'
|
14
|
+
def back! ( files=[], options={} )
|
15
|
+
sub_vcs = sub_vcs_with_name('checkout-4-vcs-back')
|
16
|
+
dir = TempPath.new('checkout-dir-4-vcs-back')
|
17
|
+
cmd = files.to_cmd
|
18
|
+
cmd.dir = dir
|
19
|
+
rev = options[:revision] || revision.read.chomp
|
20
|
+
raise ArgumentError, "Just integers are supported for revisions" if rev !~ /^\d+$/
|
21
|
+
rev = rev.to_i
|
22
|
+
target_url = url.read.chomp
|
23
|
+
while not rev.zero?
|
24
|
+
sub_vcs.checkout([target_url, dir], :quiet => true, :revision => rev)
|
25
|
+
data = cmd.system
|
26
|
+
data.display if options[:verbose]
|
27
|
+
if data.status.success?
|
28
|
+
logger.info { "Your command success on revision #{rev}"}
|
29
|
+
break
|
30
|
+
else
|
31
|
+
logger.warn { "Your command fail on revision #{rev}" }
|
32
|
+
end
|
33
|
+
rev -= 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end # class Vcs
|
data/lib/vcs/changelog.rb
CHANGED
@@ -1,164 +1,109 @@
|
|
1
1
|
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
-
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
2
|
+
# Copyright:: Copyright (c) 2004, 2005 LRDE. All rights reserved.
|
3
3
|
# License:: GNU General Public License (GPL).
|
4
4
|
# Revision:: $Id: header 98 2004-09-29 12:07:43Z ertai $
|
5
5
|
|
6
|
-
require 'vcs/vcs'
|
7
|
-
require 'vcs/svn'
|
8
6
|
|
9
|
-
class
|
7
|
+
class Vcs
|
10
8
|
|
11
|
-
@@file_st
|
9
|
+
@@file_st ||=
|
12
10
|
{
|
13
|
-
|
14
|
-
|
11
|
+
?A => 'new',
|
12
|
+
?D => 'remove',
|
15
13
|
}
|
16
|
-
@@file_st.default = ''
|
17
14
|
|
18
|
-
@@prop_st
|
15
|
+
@@prop_st ||=
|
19
16
|
{
|
20
|
-
|
17
|
+
?M => 'changed property'
|
21
18
|
}
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
20
|
+
@@entries ||= {}
|
21
|
+
|
22
|
+
def mk_log_entry_contents ( *args )
|
23
|
+
return @@entries[args] if @@entries.has_key? args
|
24
|
+
@@entries[args] = result = []
|
25
|
+
status(*args) do |se|
|
26
|
+
next if se.file_st.chr =~ /[?X\\,+]/
|
27
|
+
next if se.file.to_s == 'ChangeLog'
|
28
|
+
ls = [@@file_st[se.file_st], @@prop_st[se.prop_st]].compact!
|
29
|
+
ls.first.capitalize! unless ls.empty?
|
30
|
+
se.comment = ls.join(', ')
|
31
|
+
result << se
|
32
32
|
end
|
33
33
|
raise Failure, 'No changes, so no ChangeLog entry.' if result.empty?
|
34
34
|
result
|
35
35
|
end
|
36
|
-
private :
|
37
|
-
|
38
|
-
end # class Svn
|
39
|
-
|
36
|
+
private :mk_log_entry_contents
|
40
37
|
|
41
|
-
class Vcs
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
39
|
+
# Same switches as status
|
40
|
+
def mk_log_entry! ( *args )
|
41
|
+
with_cache! LogEntry, 'Log entry' do
|
42
|
+
mk_log_entry_contents(*args).each do |se|
|
43
|
+
puts "- #{se.file}: #{se.comment}."
|
44
|
+
end
|
48
45
|
end
|
49
46
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
def
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
cl = ADD_CL
|
61
|
-
|
62
|
-
# Already filled if ,ChangeLog.add exists and not begin by ---
|
63
|
-
if cl.exist?
|
64
|
-
raise MustBeFilled, cl if cl.read =~ /\A---/
|
65
|
-
require 'erb'
|
66
|
-
ls = []
|
67
|
-
YAML.each_document("--- |\n" + cl.read) { |x| (ls.size == 2)? break : ls << x }
|
68
|
-
title_subject, input = ls
|
69
|
-
header = { 'title' => title_subject[/^title: (.*)$/, 1],
|
70
|
-
'subject' => title_subject[/^subject: (.*)$/, 1] }
|
71
|
-
rev = revision.read.to_i + 1
|
72
|
-
header.merge!('rev' => rev, 'revision' => rev)
|
73
|
-
raise "no title: reopen #{ADD_CL}" if header['title'].nil?
|
74
|
-
header['title'].sub!(/\.$/, '')
|
75
|
-
b = getBinding(header)
|
76
|
-
header = ERB.new(header.to_yaml, $SAFE, '<-%->', '$erbout_').result(b)
|
77
|
-
META.open('w') { |f| f.puts header }
|
78
|
-
output = ERB.new(input, $SAFE, '<-%->', '$erbout_').result(b)
|
79
|
-
return output
|
47
|
+
alias_command :mkl, :mk_log_entry
|
48
|
+
LogEntry = ',log'.to_path unless defined? LogEntry
|
49
|
+
|
50
|
+
def log_to_changelog ( aString )
|
51
|
+
if aString.blank?
|
52
|
+
puts
|
53
|
+
else
|
54
|
+
putc ?\t
|
55
|
+
aString.sub!(/^-/, '*')
|
56
|
+
puts aString
|
80
57
|
end
|
58
|
+
end
|
59
|
+
private :log_to_changelog
|
81
60
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|subject: #{@@subject_format}.
|
90
|
-
|
|
91
|
-
|--- | ###################### Your ChangeLog entrie ###################### | ---
|
92
|
-
|#{head}
|
93
|
-
|
|
94
|
-
|\t<%= title %>.
|
95
|
-
|
|
96
|
-
|".head_cut!
|
97
|
-
|
98
|
-
cl_add.each do |file, str|
|
99
|
-
f.puts "\t* #{file}: #{str}."
|
100
|
-
end
|
61
|
+
# Same switches as mk_log_entry
|
62
|
+
def mk_changelog_entry! ( *args )
|
63
|
+
puts Time.now.strftime("%Y-%m-%d #{Vcs.full_email}")
|
64
|
+
puts
|
65
|
+
mk_log_entry(*args).each_line(&method(:log_to_changelog))
|
66
|
+
end
|
67
|
+
alias_command :mkcl, :mk_changelog_entry
|
101
68
|
|
102
|
-
f.puts "|
|
103
|
-
|--- | ########### This line, and those below, will be ignored ########### | ---
|
104
|
-
|Instructions:
|
105
|
-
|\t* The first line must be removed when this file is filled.
|
106
|
-
|\t* After you must specify a title, for the news/mail subject.
|
107
|
-
|\t* The line containing <%= title %> will be replaced by your title,
|
108
|
-
|\t <%= subject %> by the subject line, <%= rev %> by the revision...
|
109
|
-
|\t* Everywhere in the document you can get/compute some values with
|
110
|
-
|\t these tags <%= aRubyExpression %> even some vcs specific call.
|
111
|
-
|\t For example <%= status.read %> will include the `svn status' output.
|
112
|
-
|
|
113
|
-
|".head_cut!
|
114
|
-
with(f).diff!(*args)
|
115
|
-
end
|
116
69
|
|
117
|
-
|
70
|
+
# Same switches as mk_log_entry
|
71
|
+
def mk_message_entry! ( *args )
|
72
|
+
puts 'Index: ChangeLog'
|
73
|
+
puts "from #{Vcs.full_email}"
|
74
|
+
puts
|
75
|
+
mk_log_entry(*args).each_line(&method(:log_to_changelog))
|
118
76
|
end
|
77
|
+
alias_command :mkml, :mk_message_entry
|
119
78
|
|
120
|
-
def concat_changelog! ( *args )
|
121
|
-
error_handling :changelog_failed
|
122
|
-
|
123
|
-
if cl_entry = mkchangelog(*args)
|
124
79
|
|
125
|
-
unless TMP_CL.exist?
|
126
|
-
LOG.info "Moving `#{CL}' to `#{TMP_CL}' ..."
|
127
|
-
CL.rename(TMP_CL)
|
128
|
-
end
|
129
80
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
file.puts
|
134
|
-
file.print TMP_CL.read
|
135
|
-
end
|
81
|
+
# Same switches as mk_changelog_entry
|
82
|
+
def concat_changelog! ( *args )
|
83
|
+
error_handling :concat_changelog_failed
|
136
84
|
|
137
|
-
|
85
|
+
unless TMP_CL.exist?
|
86
|
+
logger.info "Backup your `#{CL}' to `#{TMP_CL}' ..."
|
87
|
+
CL.rename(TMP_CL)
|
88
|
+
end
|
138
89
|
|
90
|
+
CL.open('w') do |file|
|
91
|
+
logger.info "#{CL}: Writing your new entry ..."
|
92
|
+
with(file).mk_changelog_entry!(*args)
|
93
|
+
file.puts
|
94
|
+
logger.info "#{CL}: Writing the others ..."
|
95
|
+
file.print TMP_CL.read
|
139
96
|
end
|
140
97
|
end
|
98
|
+
alias_command :catcl, :concat_changelog
|
141
99
|
|
142
|
-
def
|
100
|
+
def concat_changelog_failed
|
143
101
|
if TMP_CL.exist?
|
144
|
-
|
102
|
+
logger.info "Restoring `#{CL}' from `#{TMP_CL}' ..."
|
145
103
|
TMP_CL.rename(CL)
|
146
104
|
end
|
147
|
-
LOG.info "#{ADD_CL}: Contains your ChangeLog entry" if ADD_CL.exist?
|
148
|
-
end
|
149
|
-
|
150
|
-
def getBinding ( header )
|
151
|
-
code = []
|
152
|
-
header.each do |k, v|
|
153
|
-
code << "#{k} = #{v.inspect}"
|
154
|
-
end
|
155
|
-
code << 'binding'
|
156
|
-
eval(code.join('; '))
|
157
105
|
end
|
158
|
-
protected :getBinding
|
159
106
|
|
160
|
-
alias_command :mkcl, :mkchangelog
|
161
|
-
alias_command :ctcl, :concat_changelog
|
162
107
|
|
163
108
|
end # class Vcs
|
164
109
|
|