Project

General

Profile

Regexp in time logging match does not work

Added by Sergei Plaxienko about 10 years ago

It looks like time (e.g. @5m or @0.5hours) in commit's comments are not recognize in Redmine 2.4.3.

I've tried different formats, but no luck.

My setup is: Redmine 2.4.3, Ruby 2.0.0-p247, Rails 3.2.15, git 1.8.5.1, gitlab 6.5.1

Investigation showed that regexp in app/models/changeset.rb is somehow not correct, because var hours always empty.


 TIMELOG_RE = /
    (
    ((\d+)(h|hours?))((\d+)(m|min)?)?
    |
    ((\d+)(h|hours?|m|min))
    |
    (\d+):(\d+)
    |
    (\d+([\.,]\d+)?)h?
    )
    /x

  def scan_comment_for_issue_ids
    return if comments.blank?
    # keywords used to reference issues
    ref_keywords = Setting.commit_ref_keywords.downcase.split(",").collect(&:strip)
    ref_keywords_any = ref_keywords.delete('*')
    # keywords used to fix issues
    fix_keywords = Setting.commit_update_keywords_array.map {|r| r['keywords']}.flatten.compact

    kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw)}.join("|")

    referenced_issues = []

    comments.scan(/([\s\(\[,-]|^)((#{kw_regexp})[\s:]+)?(#\d+(\s+@#{TIMELOG_RE})?([\s,;&]+#\d+(\s+@#{TIMELOG_RE})?)*)(?=[[:punct:]]|\s|<|$)/i) do |match|
      action, refs = match[2].to_s.downcase, match[3]
      next unless action.present? || ref_keywords_any

      refs.scan(/#(\d+)(\s+@#{TIMELOG_RE})?/).each do |m|
        issue, hours = find_referenced_issue_by_id(m[0].to_i), m[2]
        if issue
          referenced_issues << issue
          # Don't update issues or log time when importing old commits
          unless repository.created_on && committed_on && committed_on < repository.created_on
            fix_issue(issue, action) if fix_keywords.include?(action)
            log_time(issue, hours) if hours && Setting.commit_logtime_enabled?
          end
        end
      end
    end

TIMELOG_RE here is

(((\d+)(h|hours?))((\d+)(m|min)?)?|((\d+)(h|hours?|m|min))|(\d+):(\d+)|(\d+([\.,]\d+)?)h?)

kw_regexp here is

refs|references|issueid|fixes|closes|fixed

pre-regexp here is

([\s\(\[,-]|^)((#{kw_regexp})[\s:]+)?(#\d+(\s+@#{TIMELOG_RE})?([\s,;&]+#\d+(\s+@#{TIMELOG_RE})?)*)(?=[[:punct:]]|\s|<|$)

full-regexp here is

([\s\(\[,-]|^)((refs|references|issueid|fixes|closes|fixed)[\s:]+)?(#\d+(\s+@(((\d+)(h|hours?))((\d+)(m|min)?)?|((\d+)(h|hours?|m|min))|(\d+):(\d+)|(\d+([\.,]\d+)?)h?))?([\s,;&]+#\d+(\s+@(((\d+)(h|hours?))((\d+)(m|min)?)?|((\d+)(h|hours?|m|min))|(\d+):(\d+)|(\d+([\.,]\d+)?)h?))?)*)(?=[[:punct:]]|\s|<|$)

I've tried online regexp testers for mentioned full-regexp and try to test string refs #42 test @53m supertest, and none parsed this regexp as it supposed to be parsed:
  • http://regex101.com/ (yes, I know that this parser is for Javascript) shows match as:
    1. ``
    2. `refs`
    3. `refs`
    4. `#42`

So, no time in match.

I believe that there is a mistake or mistype in regexp, because this regexp matched correctly:

([\s\(\[,-]|^)((refs|references|issueid|fixes|closes|fixed)[\s:]+)?(#(\d+)(?:[^@]*)(?:@(((\d+)(h|hours?))((\d+)(m|min)?)?|((\d+)(h|hours?|m|min))|(\d+):(\d+)|(\d+([\.,]\d+)?)h?))?([\s,;&]+#(\d+)(?:[^@]*)(?:@(((\d+)(h|hours?))((\d+)(m|min)?)?|((\d+)(h|hours?|m|min))|(\d+):(\d+)|(\d+([\.,]\d+)?)h?))?)*)(?=[[:punct:]]|\s|<|$)

Any suggestions?