Project

General

Profile

Defect #8857 » 0001-Pass-revisions-to-git-log-via-stdin.patch

Minimal changes to pass all revisions to git-log via stdin - Jeremy Bopp, 2012-03-15 23:59

View differences:

lib/redmine/scm/adapters/abstract_adapter.rb
206 206
          self.class.logger
207 207
        end
208 208

  
209
        def shellout(cmd, &block)
210
          self.class.shellout(cmd, &block)
209
        def shellout(cmd, options = {}, &block)
210
          self.class.shellout(cmd, options, &block)
211 211
        end
212 212

  
213 213
        def self.logger
214 214
          Rails.logger
215 215
        end
216 216

  
217
        def self.shellout(cmd, &block)
217
        def self.shellout(cmd, options = {}, &block)
218 218
          if logger && logger.debug?
219 219
            logger.debug "Shelling out: #{strip_credential(cmd)}"
220 220
          end
......
223 223
            cmd = "#{cmd} 2>>#{shell_quote(Rails.root.join('log/scm.stderr.log').to_s)}"
224 224
          end
225 225
          begin
226
            if RUBY_VERSION < '1.9'
227
              mode = "r+"
228
            else
229
              mode = "r+:ASCII-8BIT"
230
            end
226
            mode = (options[:mode] || 'r').to_s
231 227
            IO.popen(cmd, mode) do |io|
232
              io.close_write
228
              io.set_encoding("ASCII-8BIT") if io.respond_to?(:set_encoding)
233 229
              block.call(io) if block_given?
234 230
            end
235 231
          ## If scm command does not exist,
lib/redmine/scm/adapters/git_adapter.rb
197 197

  
198 198
        def revisions(path, identifier_from, identifier_to, options={})
199 199
          revs = Revisions.new
200
          cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller --parents|
200
          cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller --parents --stdin|
201 201
          cmd_args << "--reverse" if options[:reverse]
202 202
          cmd_args << "-n" << "#{options[:limit].to_i}" if options[:limit]
203
          from_to = ""
203
          cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty?
204
          revisions = []
204 205
          if identifier_from || identifier_to
205
            from_to << "#{identifier_from}.." if identifier_from
206
            from_to << "#{identifier_to}" if identifier_to
207
            cmd_args << from_to if !from_to.empty?
206
            revisions << ""
207
            revisions[0] << "#{identifier_from}.." if identifier_from
208
            revisions[0] << "#{identifier_to}" if identifier_to
208 209
          else
209
            cmd_args += options[:includes] unless options[:includes].blank?
210
            unless options[:includes].blank?
211
              revisions += ignore_missing_revisions(options[:includes])
212
            end
210 213
            unless options[:excludes].blank?
211
              cmd_args << "--not"
212
              cmd_args += options[:excludes]
214
              revisions +=
215
                ignore_missing_revisions(options[:excludes]).map{|r| "^#{r}"}
213 216
            end
214 217
          end
215
          cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty?
216 218

  
217
          scm_cmd *cmd_args do |io|
219
          scm_cmd(*cmd_args, :mode => "r+") do |io|
220
            io.puts(revisions.join("\n"))
221
            io.close_write
222

  
218 223
            files=[]
219 224
            changeset = {}
220 225
            parsing_descr = 0  #0: not parsing desc or files, 1: parsing desc, 2: parsing files
......
384 389
        end
385 390

  
386 391
        def scm_cmd(*args, &block)
392
          options = args.last.kind_of?(Hash) ? args.pop : {}
387 393
          repo_path = root_url || url
388 394
          full_args = ['--git-dir', repo_path]
389 395
          if self.class.client_version_above?([1, 7, 2])
......
393 399
          full_args += args
394 400
          ret = shellout(
395 401
                   self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
402
                   options,
396 403
                   &block
397 404
                   )
398 405
          if $? && $?.exitstatus != 0
......
401 408
          ret
402 409
        end
403 410
        private :scm_cmd
411

  
412
        # Return an array containing only the given revisions that exist in the
413
        # repository.
414
        #
415
        # NOTE:
416
        # This can be removed once the minimum supported Git version supports
417
        # the --ignore-missing option for git-log and #revisions is modified to
418
        # use that option.
419
        def ignore_missing_revisions(revisions)
420
          revisions.select do |revision|
421
            begin
422
              scm_cmd(*%w|rev-parse --verify --quiet|, revision) do |io|
423
                # Read and discard the output in order to make the command
424
                # happy.
425
                io.read
426
              end
427
              true
428
            rescue ScmCommandAborted
429
              false
430
            end
431
          end
432
        end
433
        private :ignore_missing_revisions
404 434
      end
405 435
    end
406 436
  end
test/unit/lib/redmine/scm/adapters/git_adapter_test.rb
289 289
      end
290 290

  
291 291
      def test_revisions_invalid_rev_excludes
292
        assert_equal [],
293
                     @adapter.revisions('', nil, nil,
294
                                        {:reverse => true,
295
                                         :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
296
                                         :excludes => ['0123abcd4567']})
297
        assert_raise Redmine::Scm::Adapters::CommandFailed do
298
          revs1 = []
299
          @adapter.revisions('', nil, nil,
300
                             {:reverse => true,
301
                              :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
302
                              :excludes => ['0123abcd4567']}) do |rev|
303
            revs1 << rev
304
          end
292
        revs1 = @adapter.revisions('', nil, nil,
293
                                   {:reverse => true,
294
                                    :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
295
                                    :excludes => ['0123abcd4567']})
296
        assert_equal 15, revs1.length
297
        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
298
        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[ 0].identifier
299

  
300
        revs2 = []
301
        @adapter.revisions('', nil, nil,
302
                           {:reverse => true,
303
                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
304
                            :excludes => ['0123abcd4567']}) do |rev|
305
          revs2 << rev
305 306
        end
307
        assert_equal 15, revs2.length
308
        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
309
        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
306 310
      end
307 311

  
308 312
      def test_getting_revisions_with_spaces_in_filename
(7-7/8)