vcs 0.1
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/HOWTO +41 -0
- data/Rakefile +59 -0
- data/TODO +19 -0
- data/bin/vcs +139 -0
- data/bin/vcs-cvs +10 -0
- data/bin/vcs-prcs +10 -0
- data/bin/vcs-svn +10 -0
- data/lrdetools.rb +12 -0
- data/src/ask.rb +101 -0
- data/src/changelog.rb +107 -0
- data/src/cvs.rb +21 -0
- data/src/diffstat.rb +36 -0
- data/src/mail.rb +83 -0
- data/src/message.rb +58 -0
- data/src/mycommit.rb +75 -0
- data/src/news.rb +97 -0
- data/src/prcs.rb +21 -0
- data/src/reply-mail.rb +14 -0
- data/src/revision.rb +19 -0
- data/src/svn.rb +31 -0
- data/src/tools.rb +22 -0
- data/src/vcs.rb +155 -0
- metadata +65 -0
data/HOWTO
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
---
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
Mini Vcs HOWTO:
|
6
|
+
|
7
|
+
- Install Vcs:
|
8
|
+
|
9
|
+
- From a package:
|
10
|
+
|
11
|
+
- Install rubygems: http://rubyforge.org/frs/?group_id=126
|
12
|
+
|
13
|
+
- Install Vcs (as root): gem install vcs
|
14
|
+
|
15
|
+
- From the svn repository:
|
16
|
+
|
17
|
+
- Find a place to install it:
|
18
|
+
cd ~/local
|
19
|
+
|
20
|
+
- Checkout Vcs:
|
21
|
+
svn co https://svn.lrde.epita.fr/svn/lrdetools/trunk/vcs
|
22
|
+
|
23
|
+
- Update your PATH:
|
24
|
+
export PATH=$PATH:~/local/vcs/bin
|
25
|
+
|
26
|
+
- If your shell is zsh: rehash
|
27
|
+
|
28
|
+
- Check Vcs:
|
29
|
+
vcs --help
|
30
|
+
|
31
|
+
- Make aliases:
|
32
|
+
`vcs --mk-alias` # Don't forget backquotes !
|
33
|
+
|
34
|
+
- Check the transparent mode:
|
35
|
+
svn status!
|
36
|
+
|
37
|
+
- Commit in lrdetools:
|
38
|
+
svn lrdetools_commit 'Your news subject'
|
39
|
+
- or:
|
40
|
+
svn ltci 'Your news subject'
|
41
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/packagetask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
require 'rake/contrib/rubyforgepublisher'
|
7
|
+
|
8
|
+
PKG_VERSION = '0.1'
|
9
|
+
|
10
|
+
PKG_FILES = FileList[*%w"
|
11
|
+
src/**/*.rb
|
12
|
+
bin/**/*
|
13
|
+
*.rb
|
14
|
+
[A-Z]*
|
15
|
+
"].exclude(/\b\.svn\b|\..*\.sw[op]$|~$|README/)
|
16
|
+
|
17
|
+
desc 'Default Task'
|
18
|
+
task :default => :package
|
19
|
+
|
20
|
+
desc 'Publish to RubyForge'
|
21
|
+
task :rubyforge do
|
22
|
+
Rake::RubyForgePublisher.new('vcs', 'ertai').upload
|
23
|
+
end
|
24
|
+
|
25
|
+
# The Gem specification
|
26
|
+
spec = Gem::Specification.new do |s|
|
27
|
+
s.platform = Gem::Platform::RUBY
|
28
|
+
s.name = 'vcs'
|
29
|
+
s.version = PKG_VERSION
|
30
|
+
s.summary = 'A wrapper over any version control system'
|
31
|
+
s.description = '
|
32
|
+
Version control systems (Subversion, CVS, PRCS...), however useful,
|
33
|
+
are not very extensible: adding new features can be cumbersome, especially
|
34
|
+
if you want them for different such systems at once.
|
35
|
+
Vcs provide a simple dynamic hierarchy for Version Control Systems.
|
36
|
+
'
|
37
|
+
|
38
|
+
s.bindir = 'bin'
|
39
|
+
s.executables = %w[ vcs vcs-svn vcs-cvs vcs-prcs ]
|
40
|
+
s.default_executable = 'vcs'
|
41
|
+
s.files = PKG_FILES.to_a
|
42
|
+
s.require_path = 'src'
|
43
|
+
s.autorequire = 'vcs'
|
44
|
+
|
45
|
+
s.has_rdoc = false
|
46
|
+
s.author = 'Nicolas Pouillard'
|
47
|
+
s.email = 'ertai@lrde.epita.fr'
|
48
|
+
s.homepage = 'https://svn.lrde.epita.fr/svn/lrdetools/trunk/vcs/'
|
49
|
+
s.rubyforge_project = s.name
|
50
|
+
end
|
51
|
+
|
52
|
+
# Create compressed packages
|
53
|
+
Rake::GemPackageTask.new(spec) do |p|
|
54
|
+
p.gem_spec = spec
|
55
|
+
# p.need_tar = true
|
56
|
+
# p.need_zip = true
|
57
|
+
end
|
58
|
+
|
59
|
+
|
data/TODO
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
---
|
2
|
+
|
3
|
+
- add verification for ,message at commit beginning.
|
4
|
+
|
5
|
+
- |
|
6
|
+
AMHA mkcl devrait imposer une partie titre au ChangeLog.
|
7
|
+
|
8
|
+
2004- [...]
|
9
|
+
|
10
|
+
TITLE.
|
11
|
+
|
12
|
+
* Makefile.am[...]
|
13
|
+
[...]
|
14
|
+
|
15
|
+
|
16
|
+
puis utiliser ce TITLE au lieu de le demander ailleurs. Il devrait
|
17
|
+
exiger que TITLE ne soit pas trop long, et termine par un point.
|
18
|
+
|
19
|
+
- svn move avec les svn info | grep Copy des files du svn status
|
data/bin/vcs
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
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
|
+
|
6
|
+
# $LastChangedBy: ertai $
|
7
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
8
|
+
|
9
|
+
|
10
|
+
# vcs: The version control system wrapper.
|
11
|
+
#
|
12
|
+
# Vcs is a wrapper over any version control system.
|
13
|
+
|
14
|
+
require 'pathname'
|
15
|
+
require 'logger'
|
16
|
+
require 'optparse'
|
17
|
+
|
18
|
+
begin
|
19
|
+
REV="$Rev$".sub(/LastChangedRevision:\s+/, '').to_i
|
20
|
+
rescue
|
21
|
+
REV=-1
|
22
|
+
end
|
23
|
+
|
24
|
+
VCS_PATH = Pathname.new(__FILE__).expand_path
|
25
|
+
VCS_DIR, VCS = VCS_PATH.split
|
26
|
+
SRC = VCS_DIR + '..' + 'src'
|
27
|
+
$: << SRC.to_s
|
28
|
+
$: << Pathname.pwd + 'vcs'
|
29
|
+
|
30
|
+
LOG = Logger.new(STDOUT)
|
31
|
+
LOG.level = Logger::INFO
|
32
|
+
def LOG.format_message(severity, timestamp, msg, progname)
|
33
|
+
progname += ': ' unless progname.nil? or progname.empty?
|
34
|
+
"#{VCS}: #{progname}#{severity.downcase}: #{msg}\n"
|
35
|
+
end
|
36
|
+
|
37
|
+
$debug = ENV['VCS_DEBUG'].to_i
|
38
|
+
|
39
|
+
Pathname.glob("{#{SRC},vcs}/*.rb") do |file|
|
40
|
+
LOG.debug file.basename if $debug > 4
|
41
|
+
require file.basename
|
42
|
+
end
|
43
|
+
|
44
|
+
ALL_VCS_NAMES = []
|
45
|
+
ALL_VCS_BY_NAME = {}
|
46
|
+
ObjectSpace.each_object(Class) do |aClass|
|
47
|
+
if aClass != Vcs and aClass.ancestors.include? Vcs
|
48
|
+
name = aClass.to_s.to_sym
|
49
|
+
ALL_VCS_NAMES << name
|
50
|
+
ALL_VCS_BY_NAME[name] = aClass
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
OPTIONS = {}
|
55
|
+
|
56
|
+
OPTS = OptionParser.new do |opts|
|
57
|
+
|
58
|
+
opts.banner = "Usage: #{VCS} [options] <file>*"
|
59
|
+
opts.separator ''
|
60
|
+
|
61
|
+
opts.on('-c', '--vcs TYPE', ALL_VCS_NAMES, 'Set your vcs') do |aVcs|
|
62
|
+
OPTIONS[:vcs_type] = aVcs
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on('-l', '--vcs-list', 'List all vcs') do |aVcs|
|
66
|
+
STDERR.puts 'Vcs list:'
|
67
|
+
ALL_VCS_NAMES.each { |n| STDERR.puts " - #{n}" }
|
68
|
+
exit
|
69
|
+
end
|
70
|
+
|
71
|
+
opts.on('--mk-alias', 'Use this command like that `vcs --mk-alias`') do
|
72
|
+
ALL_VCS_NAMES.each do |n|
|
73
|
+
n = n.to_s.downcase
|
74
|
+
if VCS_PATH.executable?
|
75
|
+
puts "alias #{n}=#{VCS_PATH}-#{n}"
|
76
|
+
else
|
77
|
+
puts "alias #{n}=vcs-#{n}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
exit
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on('-d', '--debug LEVEL', Integer, 'Set debug level') do |anInteger|
|
84
|
+
$debug = anInteger
|
85
|
+
end
|
86
|
+
|
87
|
+
opts.on_tail('-h', '--help', 'Show this message') do |test|
|
88
|
+
STDERR.puts OPTS
|
89
|
+
exit
|
90
|
+
end
|
91
|
+
|
92
|
+
opts.on_tail('--version', 'Show version') do
|
93
|
+
STDOUT.puts "Vcs revision: #{REV}"
|
94
|
+
exit
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
if ENV.has_key? 'FULLNAME'
|
100
|
+
FULLNAME = ENV['FULLNAME']
|
101
|
+
else
|
102
|
+
require 'etc'
|
103
|
+
ENV['FULLNAME'] = (Etc.getpwnam ENV['USER']).gecos
|
104
|
+
LOG.warn "Need FULLNAME in the environement (default: #{ENV['FULLNAME']})"
|
105
|
+
end
|
106
|
+
env = %w[ EMAIL FULLNAME EDITOR PAGER ]
|
107
|
+
if env.all? { |s| ENV[s] }
|
108
|
+
env.each { |s| Kernel.const_set(s, ENV[s]) }
|
109
|
+
else
|
110
|
+
env.each { |s| LOG.error "Need #{s} in the environement" unless ENV[s] }
|
111
|
+
exit
|
112
|
+
end
|
113
|
+
FULL_EMAIL = "#{FULLNAME} <#{EMAIL}>"
|
114
|
+
|
115
|
+
def main
|
116
|
+
OPTS.parse!(ARGV)
|
117
|
+
unless OPTIONS.has_key? :vcs_type
|
118
|
+
STDERR.puts OPTS
|
119
|
+
STDERR.puts "\nSpecify at least a Vcs type, or use a wrapped command\n" +
|
120
|
+
'like svn, cvs, prcs in the vcs bin directory.'
|
121
|
+
exit
|
122
|
+
end
|
123
|
+
vcs = ALL_VCS_BY_NAME[OPTIONS[:vcs_type]].new
|
124
|
+
|
125
|
+
if ARGV.empty?
|
126
|
+
meth = :help!
|
127
|
+
else
|
128
|
+
meth = ARGV.shift.sub(/([^!])$/, '\1!')
|
129
|
+
end
|
130
|
+
|
131
|
+
vcs.send(meth, *ARGV)
|
132
|
+
end
|
133
|
+
|
134
|
+
begin
|
135
|
+
main()
|
136
|
+
rescue Exception
|
137
|
+
raise if $debug > 0
|
138
|
+
LOG.error $!.to_s.sub(/\.$/, '') unless $!.to_s == 'exit'
|
139
|
+
end
|
data/bin/vcs-cvs
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
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
|
+
|
6
|
+
# $LastChangedBy: ertai $
|
7
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
8
|
+
|
9
|
+
VCS='Cvs'
|
10
|
+
exec("vcs --vcs #{VCS} -- '#{ARGV.join(%q[' '])}'")
|
data/bin/vcs-prcs
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
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
|
+
|
6
|
+
# $LastChangedBy: ertai $
|
7
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
8
|
+
|
9
|
+
VCS='Prcs'
|
10
|
+
exec('vcs', '--vcs', VCS, '--', *ARGV)
|
data/bin/vcs-svn
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
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
|
+
|
6
|
+
# $LastChangedBy: ertai $
|
7
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
8
|
+
|
9
|
+
VCS='Svn'
|
10
|
+
exec('vcs', '--vcs', VCS, '--', *ARGV)
|
data/lrdetools.rb
ADDED
data/src/ask.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
ANSWERS = [ :y, :n ]
|
9
|
+
ANSWER_NOT_VALID = 'Not a valid answer, please answer correctly'
|
10
|
+
|
11
|
+
# `ask', ask the user to answer, to your question.
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
# ask('Commiting, are you sure', :n)
|
15
|
+
#
|
16
|
+
# produce => Commiting, are you sure (y/N):
|
17
|
+
# and wait your answer.
|
18
|
+
def ask ( aQuestion, theDefaultAnswer=:y, cin=STDIN, cout=STDOUT, cerr=STDERR )
|
19
|
+
|
20
|
+
yn = case theDefaultAnswer
|
21
|
+
when :y then ' [Y/n]: '
|
22
|
+
when :n then ' [y/N]: '
|
23
|
+
else raise ArgumentError, "not valid default answer #{theDefaultAnswer}"
|
24
|
+
end
|
25
|
+
|
26
|
+
loop do
|
27
|
+
cout.print aQuestion, yn
|
28
|
+
cout.flush
|
29
|
+
|
30
|
+
answer = cin.readline.chomp.downcase
|
31
|
+
|
32
|
+
return theDefaultAnswer if answer.empty?
|
33
|
+
|
34
|
+
answer = answer.to_sym
|
35
|
+
|
36
|
+
return answer if ANSWERS.include? answer
|
37
|
+
|
38
|
+
cerr.puts ANSWER_NOT_VALID
|
39
|
+
cout.puts
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
if defined? TEST_MODE or $0 == __FILE__
|
45
|
+
|
46
|
+
require 'test/unit'
|
47
|
+
class AskTest < Test::Unit::TestCase
|
48
|
+
|
49
|
+
def ask_checker ( question, default, answer, ref, out, err )
|
50
|
+
require 'stringio'
|
51
|
+
cin, cout, cerr = StringIO.new, StringIO.new, StringIO.new
|
52
|
+
cin.puts answer
|
53
|
+
cin.rewind
|
54
|
+
res = ask(question, default, cin, cout, cerr)
|
55
|
+
cout.rewind
|
56
|
+
cerr.rewind
|
57
|
+
assert_equal(res, ref, 'bad return value')
|
58
|
+
assert_equal(cout.readlines.join, out, 'bad standard output')
|
59
|
+
assert_equal(cerr.readlines.join, err, 'bad error output')
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_bad_default
|
63
|
+
assert_raise(ArgumentError) { ask_checker('Q', :foo, '', :y, [], []) }
|
64
|
+
assert_nothing_raised do
|
65
|
+
ask_checker('Q', :y, 'y', :y, 'Q [Y/n]: ', '')
|
66
|
+
end
|
67
|
+
assert_nothing_raised do
|
68
|
+
ask_checker('Q', :n, 'y', :y, 'Q [y/N]: ', '')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_valid_default_yes
|
73
|
+
ask_checker('Q', :y, 'y', :y, 'Q [Y/n]: ', '')
|
74
|
+
ask_checker('Q', :y, 'Y', :y, 'Q [Y/n]: ', '')
|
75
|
+
ask_checker('Q', :y, 'n', :n, 'Q [Y/n]: ', '')
|
76
|
+
ask_checker('Q', :y, 'N', :n, 'Q [Y/n]: ', '')
|
77
|
+
ask_checker('Q', :y, '', :y, 'Q [Y/n]: ', '')
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_valid_default_no
|
81
|
+
ask_checker('Q', :n, 'y', :y, 'Q [y/N]: ', '')
|
82
|
+
ask_checker('Q', :n, 'Y', :y, 'Q [y/N]: ', '')
|
83
|
+
ask_checker('Q', :n, 'n', :n, 'Q [y/N]: ', '')
|
84
|
+
ask_checker('Q', :n, 'N', :n, 'Q [y/N]: ', '')
|
85
|
+
ask_checker('Q', :n, '', :n, 'Q [y/N]: ', '')
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_invalid_answer
|
89
|
+
ask_checker('Q', :n, "bad\ny", :y,
|
90
|
+
"Q [y/N]: \nQ [y/N]: ", ANSWER_NOT_VALID + "\n")
|
91
|
+
ask_checker('Q', :y, "ad\n\n", :y,
|
92
|
+
"Q [Y/n]: \nQ [Y/n]: ", ANSWER_NOT_VALID + "\n")
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_ask1
|
96
|
+
ask_checker('Q', :y, 'y', :y, 'Q [Y/n]: ', '')
|
97
|
+
end
|
98
|
+
|
99
|
+
end # class AskTest
|
100
|
+
|
101
|
+
end
|
data/src/changelog.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
require 'vcs'
|
9
|
+
require 'svn'
|
10
|
+
|
11
|
+
class Svn
|
12
|
+
|
13
|
+
@@file_st =
|
14
|
+
{
|
15
|
+
'A' => 'New',
|
16
|
+
'D' => 'Remove',
|
17
|
+
'M' => ''
|
18
|
+
}
|
19
|
+
|
20
|
+
@@prop_st =
|
21
|
+
{
|
22
|
+
'M' => 'Changed property'
|
23
|
+
}
|
24
|
+
|
25
|
+
def mkchangelog_from_status ( *args )
|
26
|
+
result = []
|
27
|
+
status(*args).each do |line|
|
28
|
+
next unless line =~ /^.{5} /
|
29
|
+
line =~ /^(.)(.).(.).\s*(.*)$/
|
30
|
+
if $1 != '?'
|
31
|
+
file_st, prop_st, copy_st, file = @@file_st[$1], @@prop_st[$2], $3, $4
|
32
|
+
str = ''
|
33
|
+
str += file_st if file_st
|
34
|
+
str += (file_st.nil?) ? prop_st : (', ' + prop_st.downcase) if prop_st
|
35
|
+
result << [file, str]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
raise Failure, 'No changes, so no ChangeLog entry.' if result.empty?
|
39
|
+
result
|
40
|
+
end
|
41
|
+
private :mkchangelog_from_status
|
42
|
+
|
43
|
+
end # class Svn
|
44
|
+
|
45
|
+
|
46
|
+
class Vcs
|
47
|
+
|
48
|
+
class MustBeFilled < Exception
|
49
|
+
attr_reader :file
|
50
|
+
def initialize ( file )
|
51
|
+
@file = file
|
52
|
+
super("You must fill this file: `#{file.to_s}'")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def mkchangelog ( *args )
|
57
|
+
cl = ADD_CL
|
58
|
+
|
59
|
+
if cl.exist?
|
60
|
+
f = cl.open('r')
|
61
|
+
if f.readline !~ /^===/
|
62
|
+
f.rewind
|
63
|
+
return f
|
64
|
+
end
|
65
|
+
f.close
|
66
|
+
else
|
67
|
+
cl_add = mkchangelog_from_status(*args)
|
68
|
+
LOG.warn "Creating a new `#{cl}' file"
|
69
|
+
cl.open('w') do |f|
|
70
|
+
f.puts '=== Fill this file correctly and remove this line ==='
|
71
|
+
f.puts `date +"%Y-%m-%d #{FULL_EMAIL}"`
|
72
|
+
f.puts
|
73
|
+
cl_add.each do |file, str|
|
74
|
+
f.puts "\t* #{file}: #{str}."
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
raise MustBeFilled, cl
|
80
|
+
end
|
81
|
+
|
82
|
+
def changelog! ( *args )
|
83
|
+
unless CL.exist?
|
84
|
+
raise Failure, 'No ChangeLog, you are probably not in a valid directory.'
|
85
|
+
end
|
86
|
+
|
87
|
+
if cl = mkchangelog(*args)
|
88
|
+
|
89
|
+
unless TMP_CL.exist?
|
90
|
+
LOG.warn "Moving #{CL} to `#{TMP_CL}'"
|
91
|
+
CL.rename(TMP_CL)
|
92
|
+
end
|
93
|
+
|
94
|
+
CL.open('w') do |file|
|
95
|
+
cl.each { |line| file.print line }
|
96
|
+
file.puts
|
97
|
+
IO.foreach(TMP_CL) { |line| file.print line }
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
alias_command :mkcl, :mkchangelog
|
104
|
+
alias_command :cl, :changelog
|
105
|
+
|
106
|
+
end # class Vcs
|
107
|
+
|
data/src/cvs.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
require 'vcs'
|
9
|
+
|
10
|
+
class Cvs < Vcs
|
11
|
+
|
12
|
+
def initialize ( aCmd='cvs' )
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
%w[ rdiff rtag tag ].each do |m|
|
17
|
+
add_basic_method(m)
|
18
|
+
end
|
19
|
+
|
20
|
+
end # class Cvs
|
21
|
+
|
data/src/diffstat.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
require 'vcs'
|
9
|
+
|
10
|
+
class Vcs
|
11
|
+
|
12
|
+
# Use the diffstat command to
|
13
|
+
# display statitics on your patch.
|
14
|
+
def diffstat ( *a )
|
15
|
+
unless `diffstat -V` =~ /diffstat version/
|
16
|
+
raise ArgumentError, 'The `diffstat\' tool is needed by Vcs.diffstat'
|
17
|
+
end
|
18
|
+
patch = diff(*a)
|
19
|
+
rd, wr = IO.pipe
|
20
|
+
pid = fork do
|
21
|
+
rd.close
|
22
|
+
STDIN.reopen(patch)
|
23
|
+
STDOUT.reopen(wr)
|
24
|
+
exec 'diffstat'
|
25
|
+
end
|
26
|
+
wr.close
|
27
|
+
def rd.close
|
28
|
+
super
|
29
|
+
Process.waitpid pid
|
30
|
+
end
|
31
|
+
rd
|
32
|
+
end
|
33
|
+
alias_command :ds, :diffstat
|
34
|
+
|
35
|
+
end # class Vcs
|
36
|
+
|
data/src/mail.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
require 'vcs'
|
9
|
+
require 'tools'
|
10
|
+
|
11
|
+
class Vcs
|
12
|
+
|
13
|
+
MAIL = Pathname.new(',mail')
|
14
|
+
|
15
|
+
def parse_mail_options ( *args )
|
16
|
+
require 'optparse'
|
17
|
+
result =
|
18
|
+
{
|
19
|
+
:from => FULL_EMAIL,
|
20
|
+
:to => [],
|
21
|
+
:server => ENV['SMTPSERVER'] || 'localhost',
|
22
|
+
}
|
23
|
+
if !args.nil? and !args.empty? and args[0].is_a?(Hash)
|
24
|
+
args[0].each do |k,v|
|
25
|
+
result[k] = v
|
26
|
+
end
|
27
|
+
return result
|
28
|
+
end
|
29
|
+
OptionParser.new do |opts|
|
30
|
+
opts.separator ''
|
31
|
+
opts.on('-t', '--mail-to NAME', 'Choose a recipient') do |aString|
|
32
|
+
result[:to] << aString
|
33
|
+
end
|
34
|
+
opts.on('-s', '--server NAME', 'Choose a mail server') do |aString|
|
35
|
+
result[:server] = aString
|
36
|
+
end
|
37
|
+
opts.on('-S', '--subject NAME', 'Choose your mail subject') do |aString|
|
38
|
+
result[:subject] = aString.sub(/\.?$/, '.')
|
39
|
+
end
|
40
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
41
|
+
puts opts
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
end.parse!(args)
|
45
|
+
raise Failure, 'No recipents' if result[:to].empty?
|
46
|
+
raise Failure, 'No mail server' if result[:server].nil?
|
47
|
+
raise Failure, 'No mail subject' if result[:subject].nil?
|
48
|
+
result
|
49
|
+
end
|
50
|
+
protected :parse_mail_options
|
51
|
+
|
52
|
+
#
|
53
|
+
# Mail.
|
54
|
+
#
|
55
|
+
def mail ( *args )
|
56
|
+
|
57
|
+
print_body(MAIL, parse_mail_options(*args)) unless MAIL.exist?
|
58
|
+
|
59
|
+
MAIL.open('r') do |file|
|
60
|
+
opt = YAML::chop_header(file)
|
61
|
+
STDERR.puts "Smtp Server: #{opt[:server]}"
|
62
|
+
if ask("Send a mail, with this subject: #{opt[:subject]}\n" +
|
63
|
+
" to #{opt[:to].join(', ')}\n from #{opt[:from]}\n" +
|
64
|
+
'Are you sure?', :y) == :n
|
65
|
+
LOG.error 'Aborting'
|
66
|
+
exit
|
67
|
+
end
|
68
|
+
require 'net/smtp'
|
69
|
+
Net::SMTP.start(opt[:server], 25) do |smtp|
|
70
|
+
smtp.open_message_stream(EMAIL, opt[:to]) do |f|
|
71
|
+
f.print "From: #{opt[:from]}\n"
|
72
|
+
f.print "Subject: #{opt[:subject]}\n"
|
73
|
+
f.print "To: #{opt[:to].join(', ')}\n"
|
74
|
+
f.print "\n"
|
75
|
+
file.each { |line| f.print line }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
MAIL.delete
|
80
|
+
StringIO.new('Mail: Sent.')
|
81
|
+
end
|
82
|
+
|
83
|
+
end # class Vcs
|
data/src/message.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
require 'vcs'
|
9
|
+
require 'changelog'
|
10
|
+
|
11
|
+
class Vcs
|
12
|
+
def diffw ( *args )
|
13
|
+
diff(*args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Svn
|
18
|
+
def diffw ( *args )
|
19
|
+
diff('--diff-cmd', 'diff', '-x', '-NPbuw', *args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Vcs
|
24
|
+
|
25
|
+
@@message = Pathname.new(',message')
|
26
|
+
|
27
|
+
def print_body ( file, options )
|
28
|
+
LOG.warn "Creating a new `#{file}' file"
|
29
|
+
file.open('w') do |f|
|
30
|
+
f.puts options.to_yaml
|
31
|
+
f.puts '---'
|
32
|
+
f.puts
|
33
|
+
message.each do |line|
|
34
|
+
f.print line
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
private :print_body
|
39
|
+
|
40
|
+
def message ( *args )
|
41
|
+
unless @@message.exist?
|
42
|
+
cl = mkchangelog(*args)
|
43
|
+
@@message.open('w') do |f|
|
44
|
+
f.puts 'Index: ChangeLog'
|
45
|
+
cl.each { |line| f.print line.sub(/^\d+-\d+-\d+/, 'from') }
|
46
|
+
f.puts
|
47
|
+
# FIXME: need to remove the ChangeLog entry in diff.
|
48
|
+
diffstat(*args).each { |line| f.print line }
|
49
|
+
f.puts
|
50
|
+
diff(*args).each { |line| f.print line unless line =~ /^=+$/ }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
@@message.open('r')
|
54
|
+
end
|
55
|
+
|
56
|
+
alias_command :msg, :message
|
57
|
+
|
58
|
+
end # class Vcs
|
data/src/mycommit.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
require 'vcs'
|
9
|
+
require 'ask'
|
10
|
+
|
11
|
+
class Vcs
|
12
|
+
|
13
|
+
def edit! ( *files )
|
14
|
+
system(ENV['EDITOR'], *files.map { |x| x.to_s })
|
15
|
+
end
|
16
|
+
|
17
|
+
def common_commit! ( *args, &block )
|
18
|
+
|
19
|
+
opts, args = args.partition { |a| a =~ /^-/ }
|
20
|
+
|
21
|
+
update!
|
22
|
+
|
23
|
+
unless @@message.exist?
|
24
|
+
|
25
|
+
begin
|
26
|
+
mkchangelog(*args)
|
27
|
+
rescue MustBeFilled => ex
|
28
|
+
edit! ex.file
|
29
|
+
end
|
30
|
+
|
31
|
+
message(*args)
|
32
|
+
|
33
|
+
edit! @@message
|
34
|
+
|
35
|
+
changelog!(*args)
|
36
|
+
|
37
|
+
#pager! diff
|
38
|
+
#pager! status
|
39
|
+
|
40
|
+
args << 'ChangeLog' unless args.grep(/^[^-]/).empty?
|
41
|
+
|
42
|
+
if ask('Committing, are you sure?', :y) == :n
|
43
|
+
@@message.unlink
|
44
|
+
LOG.error 'Aborting'
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
|
48
|
+
if commit!('-F', ADD_CL, *(opts + args))
|
49
|
+
LOG.info 'Deleting junk files...'
|
50
|
+
ADD_CL.delete
|
51
|
+
TMP_CL.delete if TMP_CL.exist?
|
52
|
+
else
|
53
|
+
@@message.unlink
|
54
|
+
raise Failure, 'commit failed'
|
55
|
+
end
|
56
|
+
|
57
|
+
update!
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
rev = self.revision.readline.chomp.to_i
|
62
|
+
|
63
|
+
block.call(rev) if block_given?
|
64
|
+
|
65
|
+
messages = Pathname.new(',messages')
|
66
|
+
messages.mkpath unless messages.directory?
|
67
|
+
message_rev = messages + "#{@@message}.#{rev}"
|
68
|
+
LOG.info "Moving `#{@@message}' to `#{message_rev}'..."
|
69
|
+
@@message.rename(message_rev)
|
70
|
+
LOG.info "Remove `#{message_rev}' if everything is ok."
|
71
|
+
|
72
|
+
end
|
73
|
+
alias_command :cci, :common_commit
|
74
|
+
|
75
|
+
end # class Vcs
|
data/src/news.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
require 'tools'
|
9
|
+
require 'message'
|
10
|
+
|
11
|
+
class Vcs
|
12
|
+
|
13
|
+
NEWS = Pathname.new(',news')
|
14
|
+
|
15
|
+
def parse_news_options ( *args )
|
16
|
+
require 'optparse'
|
17
|
+
result =
|
18
|
+
{
|
19
|
+
:from => FULL_EMAIL,
|
20
|
+
:groups => [],
|
21
|
+
:server => ENV['NNTPSERVER'],
|
22
|
+
}
|
23
|
+
if !args.nil? and !args.empty? and args[0].is_a?(Hash)
|
24
|
+
return result.merge!(args[0])
|
25
|
+
end
|
26
|
+
OptionParser.new do |opts|
|
27
|
+
opts.separator ''
|
28
|
+
opts.on('-g', '--group NAME', 'Choose a news group') do |aString|
|
29
|
+
result[:groups] << aString
|
30
|
+
end
|
31
|
+
opts.on('-s', '--server NAME', 'Choose a news server') do |aString|
|
32
|
+
result[:server] = aString
|
33
|
+
end
|
34
|
+
opts.on('-S', '--subject NAME', 'Choose your news subject') do |aString|
|
35
|
+
result[:subject] = aString
|
36
|
+
end
|
37
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
38
|
+
puts opts
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
end.parse!(args)
|
42
|
+
raise Failure, 'No news group' if result[:groups].empty?
|
43
|
+
raise Failure, 'No news server' if result[:server].nil?
|
44
|
+
raise Failure, 'No news subject' if result[:subject].nil?
|
45
|
+
result
|
46
|
+
end
|
47
|
+
protected :parse_news_options
|
48
|
+
|
49
|
+
def check_line ( anIO, aRegex )
|
50
|
+
line = anIO.readline.chomp!
|
51
|
+
LOG.debug('news') { "Server: #{line}" }
|
52
|
+
unless line =~ aRegex
|
53
|
+
LOG.error('news') { "Bad answer: #{line}" }
|
54
|
+
@news_status = 'Error.'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
private :check_line
|
58
|
+
|
59
|
+
#
|
60
|
+
# Post the news.
|
61
|
+
#
|
62
|
+
def news ( *args )
|
63
|
+
print_body(NEWS, parse_news_options(*args)) unless NEWS.exist?
|
64
|
+
|
65
|
+
@news_status = 'Sent.'
|
66
|
+
NEWS.open('r') do |file|
|
67
|
+
opt = YAML::chop_header(file)
|
68
|
+
LOG.info('news') { "Nntp Server: #{opt[:server]}" }
|
69
|
+
if ask("Post a news, with this subject: #{opt[:subject]}\n" +
|
70
|
+
" to #{opt[:groups].join(', ')}\n from #{opt[:from]}\n" +
|
71
|
+
'Are you sure?', :y) == :n
|
72
|
+
LOG.error('news') { 'Aborting' }
|
73
|
+
exit
|
74
|
+
end
|
75
|
+
require 'socket'
|
76
|
+
TCPSocket.open(opt[:server], 119) do |f|
|
77
|
+
check_line(f, /^200/)
|
78
|
+
f.puts 'post'
|
79
|
+
check_line(f, /^340/)
|
80
|
+
f.puts "Newsgroups: #{opt[:groups].join(', ')}"
|
81
|
+
f.puts "From: #{opt[:from]}"
|
82
|
+
f.puts "Subject: #{opt[:subject]}"
|
83
|
+
f.puts
|
84
|
+
file.each do |line|
|
85
|
+
f.print line.gsub(/^\./, ' .')
|
86
|
+
end
|
87
|
+
f.puts '.'
|
88
|
+
check_line(f, /^240/)
|
89
|
+
f.puts 'quit'
|
90
|
+
check_line(f, /^205/)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
NEWS.delete
|
94
|
+
StringIO.new(@news_status)
|
95
|
+
end
|
96
|
+
|
97
|
+
end # class Vcs
|
data/src/prcs.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
require 'vcs'
|
9
|
+
|
10
|
+
class Prcs < Vcs
|
11
|
+
|
12
|
+
def initialize ( aCmd='prcs' )
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
%w[ admin ].each do |m|
|
17
|
+
add_basic_method(m)
|
18
|
+
end
|
19
|
+
|
20
|
+
end # class Prcs
|
21
|
+
|
data/src/reply-mail.rb
ADDED
data/src/revision.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
require 'svn'
|
9
|
+
require 'stringio'
|
10
|
+
|
11
|
+
class Svn
|
12
|
+
|
13
|
+
def revision ( *args )
|
14
|
+
StringIO.new(info.readlines.grep(/^Revision:/)[0].sub(/^Revision: /, ''))
|
15
|
+
end
|
16
|
+
|
17
|
+
alias_command :rev, :revision
|
18
|
+
|
19
|
+
end # class Svn
|
data/src/svn.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
require 'vcs'
|
9
|
+
require 'tools'
|
10
|
+
|
11
|
+
CL = Pathname.new('ChangeLog')
|
12
|
+
ADD_CL = Pathname.new(',ChangeLog')
|
13
|
+
TMP_CL = Pathname.new(',,ChangeLog')
|
14
|
+
|
15
|
+
class Svn < Vcs
|
16
|
+
|
17
|
+
class Failure < Vcs::Failure
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize ( aCmd='svn' )
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
%w[ blame copy list move switch revert info
|
25
|
+
propdel propget proplist propset mkdir ].each do |m|
|
26
|
+
add_basic_method(m)
|
27
|
+
end
|
28
|
+
|
29
|
+
add_basic_method!(:propedit)
|
30
|
+
|
31
|
+
end # class Svn
|
data/src/tools.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
require 'yaml'
|
9
|
+
module YAML
|
10
|
+
|
11
|
+
def self.chop_header ( io )
|
12
|
+
aStr = io.gets
|
13
|
+
raise Exception, "First line is not valid: `#{aLine}'" unless aStr =~ /^---/
|
14
|
+
io.each do |aLine|
|
15
|
+
break if aLine =~ /^---/
|
16
|
+
aStr += aLine
|
17
|
+
end
|
18
|
+
YAML::load(aStr)
|
19
|
+
end
|
20
|
+
|
21
|
+
end # module YAML
|
22
|
+
|
data/src/vcs.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2004 LRDE. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
|
5
|
+
# $LastChangedBy: ertai $
|
6
|
+
# $Id: header 98 2004-09-29 12:07:43Z ertai $
|
7
|
+
|
8
|
+
class Class # :nodoc:
|
9
|
+
|
10
|
+
def add_basic_method ( meth )
|
11
|
+
class_eval <<-end_eval
|
12
|
+
def #{meth} ( *args )
|
13
|
+
run("#{meth}", *args)
|
14
|
+
end
|
15
|
+
def #{meth}_ ( *args )
|
16
|
+
run("#{meth}", *args)
|
17
|
+
end
|
18
|
+
end_eval
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_basic_method! ( meth )
|
22
|
+
class_eval <<-end_eval
|
23
|
+
def #{meth}! ( *args )
|
24
|
+
run!("#{meth}", *args)
|
25
|
+
end
|
26
|
+
def #{meth}_! ( *args )
|
27
|
+
run!("#{meth}", *args)
|
28
|
+
end
|
29
|
+
end_eval
|
30
|
+
end
|
31
|
+
|
32
|
+
def alias_command ( m1, m2 )
|
33
|
+
class_eval <<-end_eval
|
34
|
+
def #{m1} ( *args )
|
35
|
+
#{m2}(*args)
|
36
|
+
end
|
37
|
+
def #{m1}_ ( *args )
|
38
|
+
#{m2}_(*args)
|
39
|
+
end
|
40
|
+
def #{m1}! ( *args )
|
41
|
+
#{m2}!(*args)
|
42
|
+
end
|
43
|
+
def #{m1}_! ( *args )
|
44
|
+
#{m2}_!(*args)
|
45
|
+
end
|
46
|
+
end_eval
|
47
|
+
end
|
48
|
+
|
49
|
+
end # class Class
|
50
|
+
|
51
|
+
# The abstract class for a Vcs wrapper.
|
52
|
+
# Conventions:
|
53
|
+
# example:
|
54
|
+
# svn checkout http://foo.bar/proj # normal command
|
55
|
+
# xrcs checkout http://foo.bar/proj # normal
|
56
|
+
#
|
57
|
+
# checkout
|
58
|
+
# checkout_
|
59
|
+
# checkout!
|
60
|
+
# checkout_!
|
61
|
+
#
|
62
|
+
class Vcs
|
63
|
+
|
64
|
+
class Failure < Exception
|
65
|
+
end
|
66
|
+
|
67
|
+
def initialize ( aCmd )
|
68
|
+
@cmd = aCmd
|
69
|
+
end
|
70
|
+
|
71
|
+
def common_run ( args )
|
72
|
+
cmd = @cmd + ' "' + args.join('" "') + '"'
|
73
|
+
LOG.debug "running: #{cmd}" if $debug > 1
|
74
|
+
cmd
|
75
|
+
end
|
76
|
+
private :common_run
|
77
|
+
|
78
|
+
def run ( *args )
|
79
|
+
IO.popen(common_run(args))
|
80
|
+
end
|
81
|
+
|
82
|
+
def run! ( *args )
|
83
|
+
system(common_run(args))
|
84
|
+
end
|
85
|
+
|
86
|
+
%w[ checkout delete diff help status log add update ].each do |m|
|
87
|
+
add_basic_method(m)
|
88
|
+
end
|
89
|
+
|
90
|
+
add_basic_method!(:commit)
|
91
|
+
|
92
|
+
def method_missing ( meth, *args )
|
93
|
+
meth = meth.to_s
|
94
|
+
if meth =~ /^(.*)!$/
|
95
|
+
if respond_to? $1
|
96
|
+
send($1, *args).each do |line|
|
97
|
+
puts line
|
98
|
+
end
|
99
|
+
else
|
100
|
+
LOG.warn "unknown method #{meth}"
|
101
|
+
run!($1.sub(/_$/, ''), *args)
|
102
|
+
end
|
103
|
+
else
|
104
|
+
LOG.warn "unknown method #{meth}"
|
105
|
+
run(meth.sub(/_$/, ''), *args)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
alias_command :ann, :blame
|
110
|
+
alias_command :annotate, :blame
|
111
|
+
alias_command :praise, :blame
|
112
|
+
alias_command :co, :checkout
|
113
|
+
alias_command :ci, :commit
|
114
|
+
alias_command :cp, :copy
|
115
|
+
alias_command :del, :delete
|
116
|
+
alias_command :remove, :delete
|
117
|
+
alias_command :rm, :delete
|
118
|
+
alias_command :di, :diff
|
119
|
+
alias_command :h, :help
|
120
|
+
alias_command :ls, :list
|
121
|
+
alias_command :mv, :move
|
122
|
+
alias_command :rename, :move
|
123
|
+
alias_command :ren, :move
|
124
|
+
alias_command :pdel, :propdel
|
125
|
+
alias_command :pd, :propdel
|
126
|
+
alias_command :pedit, :propedit
|
127
|
+
alias_command :pe, :propedit
|
128
|
+
alias_command :pget, :propget
|
129
|
+
alias_command :pg, :propget
|
130
|
+
alias_command :plist, :proplist
|
131
|
+
alias_command :pl, :proplist
|
132
|
+
alias_command :pset, :propset
|
133
|
+
alias_command :ps, :propset
|
134
|
+
alias_command :st, :status
|
135
|
+
alias_command :stat, :status
|
136
|
+
alias_command :sw, :switch
|
137
|
+
alias_command :up, :update
|
138
|
+
|
139
|
+
# Cvs Alias
|
140
|
+
alias_command :new, :add
|
141
|
+
alias_command :rcs, :admin
|
142
|
+
alias_command :get, :checkout
|
143
|
+
alias_command :rlog, :log
|
144
|
+
alias_command :patch, :rdiff
|
145
|
+
alias_command :remove, :delete
|
146
|
+
alias_command :rm, :delete
|
147
|
+
alias_command :rfreeze, :rtag
|
148
|
+
alias_command :freeze, :tag
|
149
|
+
|
150
|
+
# Prcs Alias
|
151
|
+
alias_command :checkin, :commit
|
152
|
+
alias_command :populate, :add
|
153
|
+
|
154
|
+
end # class Vcs
|
155
|
+
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.4
|
3
|
+
specification_version: 1
|
4
|
+
name: vcs
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: "0.1"
|
7
|
+
date: 2005-02-08
|
8
|
+
summary: A wrapper over any version control system
|
9
|
+
require_paths:
|
10
|
+
- src
|
11
|
+
email: ertai@lrde.epita.fr
|
12
|
+
homepage: https://svn.lrde.epita.fr/svn/lrdetools/trunk/vcs/
|
13
|
+
rubyforge_project: vcs
|
14
|
+
description: "Version control systems (Subversion, CVS, PRCS...), however useful, are not very
|
15
|
+
extensible: adding new features can be cumbersome, especially if you want them
|
16
|
+
for different such systems at once. Vcs provide a simple dynamic hierarchy for
|
17
|
+
Version Control Systems."
|
18
|
+
autorequire: vcs
|
19
|
+
default_executable: vcs
|
20
|
+
bindir: bin
|
21
|
+
has_rdoc: false
|
22
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
23
|
+
requirements:
|
24
|
+
-
|
25
|
+
- ">"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 0.0.0
|
28
|
+
version:
|
29
|
+
platform: ruby
|
30
|
+
authors:
|
31
|
+
- Nicolas Pouillard
|
32
|
+
files:
|
33
|
+
- src/ask.rb
|
34
|
+
- src/changelog.rb
|
35
|
+
- src/cvs.rb
|
36
|
+
- src/diffstat.rb
|
37
|
+
- src/mail.rb
|
38
|
+
- src/message.rb
|
39
|
+
- src/mycommit.rb
|
40
|
+
- src/news.rb
|
41
|
+
- src/prcs.rb
|
42
|
+
- src/reply-mail.rb
|
43
|
+
- src/revision.rb
|
44
|
+
- src/svn.rb
|
45
|
+
- src/tools.rb
|
46
|
+
- src/vcs.rb
|
47
|
+
- bin/vcs
|
48
|
+
- bin/vcs-cvs
|
49
|
+
- bin/vcs-prcs
|
50
|
+
- bin/vcs-svn
|
51
|
+
- lrdetools.rb
|
52
|
+
- HOWTO
|
53
|
+
- Rakefile
|
54
|
+
- TODO
|
55
|
+
test_files: []
|
56
|
+
rdoc_options: []
|
57
|
+
extra_rdoc_files: []
|
58
|
+
executables:
|
59
|
+
- vcs
|
60
|
+
- vcs-svn
|
61
|
+
- vcs-cvs
|
62
|
+
- vcs-prcs
|
63
|
+
extensions: []
|
64
|
+
requirements: []
|
65
|
+
dependencies: []
|