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.
@@ -0,0 +1,110 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2004, 2005 LRDE. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: header 98 2004-09-29 12:07:43Z ertai $
5
+
6
+ class Vcs
7
+
8
+ def common_commit! ( subject_format, files=[], opts={}, &block )
9
+
10
+ unless CL.exist?
11
+ raise Failure, "No `#{CL}', you are probably not in a valid directory."
12
+ end
13
+
14
+ @@subject_format = subject_format
15
+
16
+ update!
17
+
18
+ have_unrecognized_files = false
19
+ status(files) do |se|
20
+ if se.category == :unrecognize
21
+ have_unrecognized_files = true
22
+ se.colorize! if color?
23
+ puts se.line
24
+ end
25
+ end
26
+ if have_unrecognized_files
27
+ raise Failure, "
28
+ |You have unrecognized files in your working copy!
29
+ |This meant that these files won't be commited!
30
+ |You have some solutions to comply with the rule:
31
+ |- You must put these files in some categories.
32
+ | For instance you can rename these files and put a `+' before
33
+ | to make it `precious':
34
+ | put `,' for `junk'
35
+ | put `\\' for `unmask'
36
+ | put `-' for `exclude'
37
+ |- You can also edit your configuration file (.vcs) to customize
38
+ | these categories. For example add this:
39
+ | ------------ .vcs ------------
40
+ | precious:
41
+ | - !re my_precious_file[0-9]*
42
+ | - !re .*\.patch
43
+ | ------------ .vcs ------------
44
+ |- You can also perform a partial commit and specify which files
45
+ | and directories commit. For example this command:
46
+ | #{@command} commit foo.c bar/
47
+ |
48
+ |Commit failed".head_cut!
49
+ end
50
+
51
+ Vcs.commited = edit_form!(files)
52
+
53
+ mk_message(files)
54
+ edit! Message
55
+
56
+ iform = nil
57
+
58
+ if commited?
59
+ iform ||= YAML.load(IForm.read)
60
+ else
61
+
62
+ unless @h.agree 'Committing, are you sure? (y/n)', true
63
+ commit_failed
64
+ end
65
+
66
+ concat_changelog!(files)
67
+
68
+ files << 'ChangeLog' unless files.empty?
69
+
70
+ begin
71
+ commit_!(files, opts.merge(:message => mk_log_entry(files).read))
72
+ iform = YAML.load(IForm.read).merge('commited' => true)
73
+ IForm.open('w') { |f| f.print iform.to_yaml }
74
+ TMP_CL.delete if TMP_CL.exist?
75
+ rescue Exception => ex
76
+ commit_failed ex
77
+ end
78
+
79
+ update!
80
+
81
+ end
82
+
83
+ block[iform['subject']] if block_given?
84
+
85
+ logger.info 'Deleting junk files...'
86
+ TMP_CL.delete if TMP_CL.exist?
87
+ destdir = '+commited'.to_path/iform['revision'].to_s
88
+ destdir.mkpath unless destdir.directory?
89
+ [LogEntry, Form, IForm, Message, MAIL, NEWS].each do |path|
90
+ next unless path.exist?
91
+ dest = destdir/path
92
+ logger.info "Moving `#{path}' to `#{dest}'..."
93
+ path.rename(dest)
94
+ end
95
+
96
+ end
97
+ protected :common_commit!
98
+
99
+ def commit_failed ( ex=nil )
100
+ logger.error "Aborting #{ex}"
101
+ logger.info 'You can rerun the same command to resume the commit'
102
+ raise 'Commit failed'
103
+ end
104
+
105
+ cattr_accessor :commited
106
+ def commited?
107
+ Vcs.commited
108
+ end
109
+
110
+ end # class Vcs
@@ -1,16 +1,22 @@
1
+ # Copyright:: Copyright (c) 2004, 2005 LRDE. All rights reserved.
2
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
3
+ # License:: Gnu General Public License.
4
+ # Revision:: $Id$
5
+
1
6
  class Vcs
2
7
 
3
- def mk_conflicts_list
8
+ def mk_conflicts_list ( files, options={} )
4
9
  ls = status.output.readlines.grep(/^C/).map! { |s| s[/^C\s+(.*)/, 1] }
5
10
  raise "no conflicts" if ls.empty?
6
11
  ls
7
12
  end
13
+ protected :mk_conflicts_list
8
14
 
9
- def edit_conflicts!
15
+ def edit_conflicts! ( files, options={} )
10
16
  edit! mk_conflicts_list
11
17
  end
12
18
 
13
- def resolve_conflicts!
19
+ def resolve_conflicts! ( files, options={} )
14
20
  conflicts = mk_conflicts_list
15
21
  question = "Resolve these conflicts?: \n - #{conflicts.join("\n - ")}\n(y/n)"
16
22
  if @h.agree question, true
@@ -1,9 +1,7 @@
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 $
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2004, 2005 LRDE. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: header 98 2004-09-29 12:07:43Z ertai $
7
5
 
8
6
  require 'vcs/vcs'
9
7
 
@@ -18,4 +16,3 @@ class Cvs < Vcs
18
16
  end
19
17
 
20
18
  end # class Cvs
21
-
@@ -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: delete.rb 265 2005-10-03 12:37:03Z pouill_n $
5
+
6
+ class Vcs
7
+
8
+ specific_options << '--auto'
9
+
10
+ def delete! ( files=[], options={} )
11
+ if options[:auto]
12
+ options.delete(:auto)
13
+ list!(files, :missing => true) do |path_list|
14
+ delete_!(path_list.stringify, options) unless path_list.empty?
15
+ end
16
+ else
17
+ delete_!(files, options)
18
+ end
19
+ end
20
+
21
+ end # class Vcs
@@ -3,16 +3,36 @@
3
3
  # License:: GNU General Public License (GPL).
4
4
  # Revision:: $Id$
5
5
 
6
- class Svn
7
-
8
- def diffw_from_status! ( *args )
9
- files = Set.new
10
- from_status(*args) do |line, file_st, prop_st, cpy, file|
11
- next if file_st =~ /[?X]/
12
- next if file == 'ChangeLog'
13
- files << Pathname.new(file)
6
+ class Vcs
7
+
8
+ def diffw! ( *args )
9
+ diff_!(*args)
10
+ end
11
+
12
+ def check_gnu_diff
13
+ unless `diff --version` =~ /GNU/
14
+ raise ArgumentError, 'diffw: Gnu diff is required'
15
+ end
16
+ end
17
+ add_conf_checker :check_gnu_diff
18
+
19
+ end # class Vcs
20
+
21
+
22
+ class Svn < Vcs
23
+
24
+ # A diff only for your eyes
25
+ def diffw! ( files_orig=[], options={} )
26
+ files = []
27
+ status(files_orig) do |se|
28
+ next if se.file_st.chr =~ /[?X\\,+D]/
29
+ next if se.file.to_s == 'ChangeLog'
30
+ next if se.file.directory?
31
+ files << se.file unless files.include? se.file
14
32
  end
15
- diffw!(*files.delete_if { |f| f.directory? })
33
+ return if files.empty? and not files_orig.empty?
34
+ diff_! files,
35
+ options.merge(:diff_cmd => 'diff', :extensions => '-NPbuw')
16
36
  end
17
37
 
18
38
  end # class Svn
@@ -1,5 +1,5 @@
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$
5
5
 
@@ -12,13 +12,13 @@ class Vcs
12
12
  # display statitics on your patch.
13
13
  def diffstat! ( *a )
14
14
  check_diffstat
15
- (diff(*a) | @@diffstat).run(@runner)
15
+ (diffw(*a) | @@diffstat).run(@runner)
16
16
  end
17
17
  alias_command :ds, :diffstat
18
18
 
19
19
  def check_diffstat
20
20
  unless `diffstat -V` =~ /diffstat version/
21
- raise ArgumentError, 'The `diffstat\' tool is needed by Vcs.diffstat'
21
+ raise ArgumentError, 'diffstat: diffstat is required'
22
22
  end
23
23
  end
24
24
 
@@ -1,15 +1,14 @@
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
- # Revision:: $Id: edit.rb 225 2005-09-16 14:09:22Z pouill_n $
4
+ # Revision:: $Id: edit.rb 244 2005-09-29 12:45:05Z pouill_n $
5
5
 
6
6
  require 'vcs/vcs'
7
7
 
8
8
  class Vcs
9
9
 
10
- def edit! ( *files )
11
- # stringify
12
- cmd = EDITOR + files.flatten.map { |x| x.to_s } > [STDOUT, STDERR]
10
+ def edit! ( files=[], options={} )
11
+ cmd = Vcs.editor + files > [STDOUT, STDERR]
13
12
  cmd.run(@runner)
14
13
  end
15
14
 
@@ -0,0 +1,59 @@
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: environment.rb 242 2005-09-28 14:19:47Z pouill_n $
5
+
6
+ class Vcs
7
+
8
+ class << self
9
+
10
+ def fullname
11
+ env('FULLNAME') { Etc.getpwnam(user).gecos }
12
+ end
13
+
14
+ def editor
15
+ env('EDITOR').to_cmd
16
+ end
17
+
18
+ def pager
19
+ env('PAGER').to_cmd
20
+ end
21
+
22
+ def full_email
23
+ "#{fullname} <#{email}>"
24
+ end
25
+
26
+ def method_missing ( meth )
27
+ env meth.to_s.upcase
28
+ end
29
+
30
+ @@vars ||= {}
31
+ @@env_status ||= true
32
+
33
+ def env ( name, &block )
34
+ return @@vars[name] if @@vars.has_key? name
35
+ @@vars[name] =
36
+ if var = ENV[name]
37
+ var
38
+ elsif block.nil?
39
+ logger.error "Need #{name} in the environement"
40
+ @@env_status = false
41
+ "!!! #{name} not set !!!"
42
+ else
43
+ default = block[]
44
+ logger.warn "Need #{name} in the environement (default: #{default})"
45
+ ENV[name] = default
46
+ default
47
+ end
48
+ end
49
+
50
+ end # class << self
51
+
52
+ def check_env
53
+ %w[ email fullname editor pager ].each { |m| Vcs.send(m) }
54
+ end
55
+
56
+ add_conf_checker :check_env
57
+
58
+ end # class Vcs
59
+
@@ -0,0 +1,97 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005 LRDE. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: form.rb 266 2005-10-03 13:11:29Z pouill_n $
5
+
6
+ class Vcs
7
+
8
+ def edit_form! ( *args )
9
+ mk_form(*args)
10
+ edit! Form if Form.read =~ /\A---/
11
+ if Form.read =~ /\A---/
12
+ raise Failure, "You must fill this file: `#{Form}' (and remove the first line)"
13
+ else
14
+ mk_iform(*args)
15
+ return YAML.load(IForm.read)['commited']
16
+ end
17
+ end
18
+
19
+
20
+ def mk_iform! ( *args )
21
+ with_cache! IForm, 'instanciated form (title, subject, ChangeLog entry, diff)' do
22
+ cl = mk_form(*args).read
23
+ ls = []
24
+ YAML.each_document("--- |\n" + cl) { |x| (ls.size == 2)? break : ls << x }
25
+ title_subject, input = ls
26
+ header = { 'title' => title_subject[/^title: (.*)$/, 1],
27
+ 'subject' => title_subject[/^subject: (.*)$/, 1] }
28
+ rev = revision.read.to_i + 1
29
+ header.merge!('revision' => rev, 'commited' => false)
30
+ if header['title'].nil? or header['title'].blank?
31
+ raise Failure, "No title found. Reopen `#{Form}' and add it"
32
+ end
33
+ header['title'] += '.' unless header['title'] =~ /[.?!]$/
34
+ b = getBinding(header.merge(:rev => rev))
35
+ input = ERB.new(input, nil, '<-%->', '$erbout_').result(b)
36
+ LogEntry.open('w') { |f| f.print input }
37
+ header.each_value do |v|
38
+ next unless v.is_a? String
39
+ v.replace(ERB.new(v, nil, '<-%->', '$erbout_').result(b))
40
+ end
41
+ puts header.to_yaml
42
+ end
43
+ end
44
+ IForm = ',iform'.to_path unless defined? Vcs::IForm
45
+
46
+
47
+ @@subject_format ||= '<%= rev %>: <%= title %>'
48
+
49
+ def mk_form! ( files=[], options={} )
50
+ with_cache! Form, 'complete form (title, subject, ChangeLog entry, diff)' do
51
+
52
+ puts "
53
+ |--- | ########## Fill this file correctly and remove this line ########## | ---
54
+ |title:
55
+ |subject: #{@@subject_format}
56
+ |
57
+ |--- | ###################### Your ChangeLog entry ############### 80c| # | ---
58
+ |<%= title %>
59
+ |
60
+ |".head_cut!
61
+
62
+ mk_log_entry!(files)
63
+
64
+ puts "|
65
+ |--- | ########### This line, and those below, will be ignored #### 80c| # | ---
66
+ |Instructions:
67
+ |- The first line must be removed when this file is filled.
68
+ |- After you must specify a title, for the news/mail subject.
69
+ | The line containing <%= title %> will be replaced by your title,
70
+ | <%= subject %> by the subject line, <%= rev %> by the revision...
71
+ |- Everywhere in the document you can get/compute some values with
72
+ | these tags <%= aRubyExpression %> even some vcs specific call.
73
+ | For example <%= status.read %> will include the 'svn status' output.
74
+ |- Tabulations and stars ('*') will be added in the ChangeLog before each line.
75
+ |- The '80c|' on the fourth line is here to show you where will be the
76
+ | limit. The '|' is the 79th char.
77
+ |
78
+ |".head_cut!
79
+
80
+ diffw!(files)
81
+ end
82
+ end
83
+ alias_command :mkf, :mk_form
84
+ Form = ',form'.to_path unless defined? Vcs::Form
85
+
86
+ def getBinding ( header )
87
+ code = []
88
+ header.each do |k, v|
89
+ code << "#{k} = #{v.inspect}"
90
+ end
91
+ code << 'binding'
92
+ eval(code.join('; '))
93
+ end
94
+ protected :getBinding
95
+
96
+ end # class Vcs
97
+
@@ -0,0 +1,26 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005 LRDE. All rights reserved.
3
+ # License:: Gnu General Public License.
4
+ # Revision:: $Id: ignore.rb 260 2005-10-02 20:22:46Z pouill_n $
5
+
6
+
7
+ class Svn
8
+
9
+ # Add an ignore entry in the given path. Automatically determine the rep
10
+ # concerned with svn:ignore.
11
+ # Examples:
12
+ # $ svn ignore my_subdir/'*.tex'
13
+ # $ svn ignore ./foo.generated my_subdir/another/a_wrong_file
14
+ def ignore! ( files=[], options={} )
15
+ files.each do |file|
16
+ dir, base = file.to_path.split
17
+ logger.info { "Add `#{base}' to svn:ignore of `#{dir}'"}
18
+ data = propget(['svn:ignore', dir], :strict => true)
19
+ data.output.open('a') { |f| f.puts base }
20
+ propset!(['svn:ignore', dir],
21
+ options.merge(:quiet => true, :file => data.output))
22
+ data.clean
23
+ end
24
+ end
25
+
26
+ end # class Svn