Revision 1297:0a574315af3e .svn/pristine/8f

View differences:

.svn/pristine/8f/8f7d415c01cd1aa2a9653282ae2c4dbd9a43ab03.svn-base
1
#!/usr/bin/env ruby
2

  
3
require 'optparse'
4
require 'find'
5
require 'etc'
6
require 'rubygems'
7

  
8
Version = "1.4"
9
SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
10

  
11
$verbose      = 0
12
$quiet        = false
13
$redmine_host = ''
14
$repos_base   = ''
15
$svn_owner    = 'root'
16
$svn_group    = 'root'
17
$use_groupid  = true
18
$svn_url      = false
19
$test         = false
20
$force        = false
21
$scm          = 'Subversion'
22

  
23
def log(text, options={})
24
  level = options[:level] || 0
25
  puts text unless $quiet or level > $verbose
26
  exit 1 if options[:exit]
27
end
28

  
29
def system_or_raise(command)
30
  raise "\"#{command}\" failed" unless system command
31
end
32

  
33
module SCM
34

  
35
  module Subversion
36
    def self.create(path)
37
      system_or_raise "svnadmin create #{path}"
38
    end
39
  end
40

  
41
  module Git
42
    def self.create(path)
43
      Dir.mkdir path
44
      Dir.chdir(path) do
45
        system_or_raise "git --bare init --shared"
46
        system_or_raise "git update-server-info"
47
      end
48
    end
49
  end
50

  
51
end
52

  
53
def read_key_from_file(filename)
54
  begin
55
    $api_key = File.read(filename).strip
56
  rescue Exception => e
57
    $stderr.puts "Unable to read the key from #{filename}: #{e.message}"
58
    exit 1
59
  end
60
end
61

  
62
def set_scm(scm)
63
  $scm = scm.capitalize
64
  unless SUPPORTED_SCM.include?($scm)
65
    log("Invalid SCM: #{$scm}\nValid SCM are: #{SUPPORTED_SCM.join(', ')}", :exit => true)
66
  end
67
end
68

  
69
optparse = OptionParser.new do |opts|
70
  opts.banner = "Usage: reposman.rb [OPTIONS...] -s [DIR] -r [HOST] -k [KEY]"
71
  opts.separator("")
72
  opts.separator("Manages your repositories with Redmine.")
73
  opts.separator("")
74
  opts.separator("Required arguments:") 
75
  opts.on("-s", "--svn-dir DIR",      "use DIR as base directory for svn repositories") {|v| $repos_base = v}
76
  opts.on("-r", "--redmine-host HOST","assume Redmine is hosted on HOST. Examples:",
77
                                       " -r redmine.example.net",
78
                                       " -r http://redmine.example.net",
79
                                       " -r https://redmine.example.net") {|v| $redmine_host = v}
80
  opts.on("-k", "--key KEY",           "use KEY as the Redmine API key",
81
                                       "(you can use --key-file option as an alternative)") {|v| $api_key = v}
82
  opts.separator("")
83
  opts.separator("Options:")
84
  opts.on("-o", "--owner OWNER",       "owner of the repository. using the rails login", 
85
                                       "allows users to browse the repository within",
86
                                       "Redmine even for private projects. If you want to",
87
                                       "share repositories through Redmine.pm, you need",
88
                                       "to use the apache owner.") {|v| $svn_owner = v; $use_groupid = false}
89
  opts.on("-g", "--group GROUP",       "group of the repository (default: root)") {|v| $svn_group = v; $use_groupid = false}
90
  opts.on("-u", "--url URL",           "the base url Redmine will use to access your",
91
                                       "repositories. This option is used to register",
92
                                       "the repositories in Redmine automatically. The",
93
                                       "project identifier will be appended to this url.",
94
                                       "Examples:",
95
                                       " -u https://example.net/svn",
96
                                       " -u file:///var/svn/",
97
                                       "if this option isn't set, reposman won't register",
98
                                       "the repositories in Redmine") {|v| $svn_url = v}
99
  opts.on(      "--scm SCM",           "the kind of SCM repository you want to create",
100
                                       "(and register) in Redmine (default: Subversion).",
101
                                       "reposman is able to create Git and Subversion",
102
                                       "repositories.",
103
                                       "For all other kind, you must specify a --command",
104
                                       "option") {|v| set_scm(v)}
105
  opts.on("-c", "--command COMMAND",   "use this command instead of `svnadmin create` to",
106
                                       "create a repository. This option can be used to",
107
                                       "create repositories other than subversion and git",
108
                                       "kind.",
109
                                       "This command override the default creation for",
110
                                       "git and subversion.") {|v| $command = v}
111
  opts.on(      "--key-file FILE",     "path to a file that contains the Redmine API key",
112
                                       "(use this option instead of --key if you don't", 
113
                                       "want the key to appear in the command line)") {|v| read_key_from_file(v)}
114
  opts.on("-t", "--test",              "only show what should be done") {$test = true}
115
  opts.on("-f", "--force",             "force repository creation even if the project", "repository is already declared in Redmine") {$force = true}
116
  opts.on("-v", "--verbose",           "verbose") {$verbose += 1}
117
  opts.on("-V", "--version",           "show version and exit") {puts Version; exit}
118
  opts.on("-h", "--help",              "show help and exit") {puts opts; exit 1}
119
  opts.on("-q", "--quiet",             "no log") {$quiet = true}
120
  opts.separator("")
121
  opts.separator("Examples:")
122
  opts.separator("  reposman.rb --svn-dir=/var/svn --redmine-host=redmine.host")
123
  opts.separator("  reposman.rb -s /var/git -r redmine.host -u http://git.host --scm git")
124
  opts.separator("")
125
  opts.separator("You can find more information on the redmine's wiki:\nhttp://www.redmine.org/projects/redmine/wiki/HowTos")
126

  
127
  opts.summary_width = 25
128
end
129
optparse.parse!
130

  
131
if $test
132
  log("running in test mode")
133
end
134

  
135
# Make sure command is overridden if SCM vendor is not handled internally (for the moment Subversion and Git)
136
if $command.nil?
137
  begin
138
    scm_module = SCM.const_get($scm)
139
  rescue
140
    log("Please use --command option to specify how to create a #{$scm} repository.", :exit => true)
141
  end
142
end
143

  
144
$svn_url += "/" if $svn_url and not $svn_url.match(/\/$/)
145

  
146
if ($redmine_host.empty? or $repos_base.empty?)
147
  puts "Some arguments are missing. Use reposman.rb --help for getting help."
148
  exit 1
149
end
150

  
151
unless File.directory?($repos_base)
152
  log("directory '#{$repos_base}' doesn't exists", :exit => true)
153
end
154

  
155
begin
156
  require 'active_resource'
157
rescue LoadError
158
  log("This script requires activeresource.\nRun 'gem install activeresource' to install it.", :exit => true)
159
end
160

  
161
class Project < ActiveResource::Base
162
  self.headers["User-agent"] = "Redmine repository manager/#{Version}"
163
  self.format = :xml
164
end
165

  
166
log("querying Redmine for projects...", :level => 1);
167

  
168
$redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
169
$redmine_host.gsub!(/\/$/, '')
170

  
171
Project.site = "#{$redmine_host}/sys";
172

  
173
begin
174
  # Get all active projects that have the Repository module enabled
175
  projects = Project.find(:all, :params => {:key => $api_key})
176
rescue ActiveResource::ForbiddenAccess
177
  log("Request was denied by your Redmine server. Make sure that 'WS for repository management' is enabled in application settings and that you provided the correct API key.")
178
rescue => e
179
  log("Unable to connect to #{Project.site}: #{e}", :exit => true)
180
end
181

  
182
if projects.nil?
183
  log('No project found, perhaps you forgot to "Enable WS for repository management"', :exit => true)
184
end
185

  
186
log("retrieved #{projects.size} projects", :level => 1)
187

  
188
def set_owner_and_rights(project, repos_path, &block)
189
  if mswin?
190
    yield if block_given?
191
  else
192
    uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : Etc.getgrnam($svn_group).gid)
193
    right = project.is_public ? 0775 : 0770
194
    yield if block_given?
195
    Find.find(repos_path) do |f|
196
      File.chmod right, f
197
      File.chown uid, gid, f
198
    end
199
  end
200
end
201

  
202
def other_read_right?(file)
203
  (File.stat(file).mode & 0007).zero? ? false : true
204
end
205

  
206
def owner_name(file)
207
  mswin? ?
208
    $svn_owner :
209
    Etc.getpwuid( File.stat(file).uid ).name
210
end
211

  
212
def mswin?
213
  (RUBY_PLATFORM =~ /(:?mswin|mingw)/) || (RUBY_PLATFORM == 'java' && (ENV['OS'] || ENV['os']) =~ /windows/i)
214
end
215

  
216
projects.each do |project|
217
  log("treating project #{project.name}", :level => 1)
218

  
219
  if project.identifier.empty?
220
    log("\tno identifier for project #{project.name}")
221
    next
222
  elsif not project.identifier.match(/^[a-z0-9\-_]+$/)
223
    log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
224
    next;
225
  end
226

  
227
  repos_path = File.join($repos_base, project.identifier).gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
228

  
229
  if File.directory?(repos_path)
230
    # we must verify that repository has the good owner and the good
231
    # rights before leaving
232
    other_read = other_read_right?(repos_path)
233
    owner      = owner_name(repos_path)
234
    next if project.is_public == other_read and owner == $svn_owner
235

  
236
    if $test
237
      log("\tchange mode on #{repos_path}")
238
      next
239
    end
240

  
241
    begin
242
      set_owner_and_rights(project, repos_path)
243
    rescue Errno::EPERM => e
244
      log("\tunable to change mode on #{repos_path} : #{e}\n")
245
      next
246
    end
247

  
248
    log("\tmode change on #{repos_path}");
249

  
250
  else
251
    # if repository is already declared in redmine, we don't create
252
    # unless user use -f with reposman
253
    if $force == false and project.respond_to?(:repository)
254
      log("\trepository for project #{project.identifier} already exists in Redmine", :level => 1)
255
      next
256
    end
257

  
258
    project.is_public ? File.umask(0002) : File.umask(0007)
259

  
260
    if $test
261
      log("\tcreate repository #{repos_path}")
262
      log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}") if $svn_url;
263
      next
264
    end
265

  
266
    begin
267
      set_owner_and_rights(project, repos_path) do
268
        if scm_module.nil?
269
          system_or_raise "#{$command} #{repos_path}"
270
        else
271
          scm_module.create(repos_path)
272
        end
273
      end
274
    rescue => e
275
      log("\tunable to create #{repos_path} : #{e}\n")
276
      next
277
    end
278

  
279
    if $svn_url
280
      begin
281
        project.post(:repository, :vendor => $scm, :repository => {:url => "#{$svn_url}#{project.identifier}"}, :key => $api_key)
282
        log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
283
      rescue => e
284
        log("\trepository #{repos_path} not registered in Redmine: #{e.message}");
285
      end
286
    end
287
    log("\trepository #{repos_path} created");
288
  end
289
end
.svn/pristine/8f/8fa37bd50f73aaaf794ed1e7474b6ffe3abf2008.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2012  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
module Redmine
19
  module Utils
20
    class << self
21
      # Returns the relative root url of the application
22
      def relative_url_root
23
        ActionController::Base.respond_to?('relative_url_root') ?
24
          ActionController::Base.relative_url_root.to_s :
25
          ActionController::Base.config.relative_url_root.to_s
26
      end
27

  
28
      # Sets the relative root url of the application
29
      def relative_url_root=(arg)
30
        if ActionController::Base.respond_to?('relative_url_root=')
31
          ActionController::Base.relative_url_root=arg
32
        else
33
          ActionController::Base.config.relative_url_root = arg
34
        end
35
      end
36

  
37
      # Generates a n bytes random hex string
38
      # Example:
39
      #   random_hex(4) # => "89b8c729"
40
      def random_hex(n)
41
        SecureRandom.hex(n)
42
      end
43
    end
44

  
45
    module Shell
46
      def shell_quote(str)
47
        if Redmine::Platform.mswin?
48
          '"' + str.gsub(/"/, '\\"') + '"'
49
        else
50
          "'" + str.gsub(/'/, "'\"'\"'") + "'"
51
        end
52
      end
53
    end
54

  
55
    module DateCalculation
56
      # Returns the number of working days between from and to
57
      def working_days(from, to)
58
        days = (to - from).to_i
59
        if days > 0
60
          weeks = days / 7
61
          result = weeks * (7 - non_working_week_days.size)
62
          days_left = days - weeks * 7
63
          start_cwday = from.cwday
64
          days_left.times do |i|
65
            unless non_working_week_days.include?(((start_cwday + i - 1) % 7) + 1)
66
              result += 1
67
            end
68
          end
69
          result
70
        else
71
          0
72
        end
73
      end
74

  
75
      # Adds working days to the given date
76
      def add_working_days(date, working_days)
77
        if working_days > 0
78
          weeks = working_days / (7 - non_working_week_days.size)
79
          result = weeks * 7
80
          days_left = working_days - weeks * (7 - non_working_week_days.size)
81
          cwday = date.cwday
82
          while days_left > 0
83
            cwday += 1
84
            unless non_working_week_days.include?(((cwday - 1) % 7) + 1)
85
              days_left -= 1
86
            end
87
            result += 1
88
          end
89
          next_working_date(date + result)
90
        else
91
          date
92
        end
93
      end
94

  
95
      # Returns the date of the first day on or after the given date that is a working day
96
      def next_working_date(date)
97
        cwday = date.cwday
98
        days = 0
99
        while non_working_week_days.include?(((cwday + days - 1) % 7) + 1)
100
          days += 1
101
        end
102
        date + days
103
      end
104

  
105
      # Returns the index of non working week days (1=monday, 7=sunday)
106
      def non_working_week_days
107
        @non_working_week_days ||= begin
108
          days = Setting.non_working_week_days
109
          if days.is_a?(Array) && days.size < 7
110
            days.map(&:to_i)
111
          else
112
            []
113
          end
114
        end
115
      end
116
    end
117
  end
118
end
.svn/pristine/8f/8fb92a4b5691357b3504f3727bbca8084c1fed1a.svn-base
1
Return-Path: <JSmith@somenet.foo>
2
Received: from osiris ([127.0.0.1])
3
	by OSIRIS
4
	with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200
5
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>
6
From: "John Smith" <JSmith@somenet.foo>
7
To: <redmine@somenet.foo>
8
Subject: New ticket on a given project with a very long subject line which exceeds 255 chars and should not be ignored but chopped off. And if the subject line is still not long enough, we just add more text. And more text. Wow, this is really annoying. Especially, if you have nothing to say...
9
Date: Sun, 22 Jun 2008 12:28:07 +0200
10
MIME-Version: 1.0
11
Content-Type: text/plain;
12
	format=flowed;
13
	charset="iso-8859-1";
14
	reply-type=original
15
Content-Transfer-Encoding: 7bit
16
X-Priority: 3
17
X-MSMail-Priority: Normal
18
X-Mailer: Microsoft Outlook Express 6.00.2900.2869
19
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869
20

  
21
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet 
22
turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus 
23
blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti 
24
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In 
25
in urna sed tellus aliquet lobortis. Morbi scelerisque tortor in dolor. Cras 
26
sagittis odio eu lacus. Aliquam sem tortor, consequat sit amet, vestibulum 
27
id, iaculis at, lectus. Fusce tortor libero, congue ut, euismod nec, luctus 
28
eget, eros. Pellentesque tortor enim, feugiat in, dignissim eget, tristique 
29
sed, mauris --- Pellentesque habitant morbi tristique senectus et netus et 
30
malesuada fames ac turpis egestas. Quisque sit amet libero. In hac habitasse 
31
platea dictumst.
32

  
33
--- This line starts with a delimiter and should not be stripped
34

  
35
This paragraph is before delimiters.
36

  
37
BREAK
38

  
39
This paragraph is between delimiters.
40

  
41
---
42

  
43
This paragraph is after the delimiter so it shouldn't appear.
44

  
45
Nulla et nunc. Duis pede. Donec et ipsum. Nam ut dui tincidunt neque 
46
sollicitudin iaculis. Duis vitae dolor. Vestibulum eget massa. Sed lorem. 
47
Nullam volutpat cursus erat. Cras felis dolor, lacinia quis, rutrum et, 
48
dictum et, ligula. Sed erat nibh, gravida in, accumsan non, placerat sed, 
49
massa. Sed sodales, ante fermentum ultricies sollicitudin, massa leo 
50
pulvinar dui, a gravida orci mi eget odio. Nunc a lacus.
51

  
52
Project: onlinestore
53
Status: Resolved
54
due date: 2010-12-31
55
Start Date:2010-01-01
56
Assigned to: John Smith
57

  
.svn/pristine/8f/8fdff2fea815e65bfcdb8ed501cd30a4424623ff.svn-base
1
<div class="autoscroll">
2
<table class="filecontent syntaxhl">
3
<tbody>
4
<% line_num = 1 %>
5
<% syntax_highlight_lines(filename, Redmine::CodesetUtil.to_utf8_by_setting(content)).each do |line| %>
6
  <tr>
7
    <th class="line-num" id="L<%= line_num %>">
8
      <a href="#L<%= line_num %>"><%= line_num %></a>
9
    </th>
10
    <td class="line-code">
11
      <pre><%= line.html_safe %></pre>
12
    </td>
13
  </tr>
14
  <% line_num += 1 %>
15
<% end %>
16
</tbody>
17
</table>
18
</div>

Also available in: Unified diff