Module: Issuesrc

Defined in:
lib/issuesrc.rb,
lib/issuesrc/tag.rb,
lib/issuesrc/file.rb,
lib/issuers/issuers.rb,
lib/issuesrc/config.rb,
lib/issuesrc/version.rb,
lib/sourcers/sourcers.rb,
lib/issuesrc/event_loop.rb,
lib/sourcers/git_sourcer.rb,
lib/issuers/github_issuer.rb,
lib/issuesrc/tag_extractor.rb,
lib/sourcers/github_sourcer.rb,
lib/tag_finders/tag_finders.rb,
lib/tag_finders/blunt_tag_finder.rb

Defined Under Namespace

Modules: Config, Issuers, Sourcers, TagFinders Classes: EventLoop, FSFile, FileInterface, GitFile, IssuesrcError, SequentialEventLoop, Tag, TagExtractor

Constant Summary collapse

DEFAULT_SOURCER =
'github'
DEFAULT_ISSUER =
'github'
DEFAULT_TAG_FINDERS =
['blunt']
SOURCERS =
{
  'git' => ['sourcers/git_sourcer', 'GitSourcer'],
  'github' => ['sourcers/github_sourcer', 'GithubSourcer'],
}
ISSUERS =
{
  'github' => ['issuers/github_issuer', 'GithubIssuer'],
}
TAG_FINDERS =
{
  'blunt' => ['tag_finders/blunt_tag_finder', 'BluntTagFinder'],
}
VERSION =
"0.0.5"
TAG_EXTRACTORS =
[
  {
    'regexp' => /(?<type>TODO|FIXME|BUG)\s*(\(\s*(?<author>[^)#\s]+)?\s*(#\s*(?<issue_id>[^)\s]+))?\s*\))?\s*:?\s*(?<title>[^\s].*)?/,
  }
]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#files_offsetsObject

Returns the value of attribute files_offsets


92
93
94
# File 'lib/issuesrc.rb', line 92

def files_offsets
  @files_offsets
end

Class Method Details

.exec_fail(feedback) ⇒ Object

Raises:


210
211
212
# File 'lib/issuesrc.rb', line 210

def self.exec_fail(feedback)
  raise IssuesrcError, feedback
end

.run(args, config) ⇒ Object

Run issuesrc.


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/issuesrc.rb', line 30

def self.run(args, config)
  program = Class.new { include Issuesrc }.new
  program.set_config(args, config)
  program.init_files_offsets()

  event_loop = Issuesrc::SequentialEventLoop.new()
  sourcer = program.load_sourcer()
  tag_finders = program.load_tag_finders()
  issuer = program.load_issuer(event_loop)

  issues = issuer.async_load_issues()

  created_tags, updated_tags, closed_issues = [], [], []
  tags_by_issue_id = {}

  sourcer.retrieve_files().each do |file|
    if Issuesrc::Config.option_from_args(:verbose, args)
      puts file.path
    end

    tag_finder = program.select_tag_finder_for(file, tag_finders)
    if tag_finder.nil?
      next
    end

    tags = []
    tag_finder.find_tags(file) { |tag| tags << tag }

    tags_in_file, new_tags = program.classify_tags(tags)
    tags_by_issue_id.update(tags_in_file)

    new_tags.each do |tag|
      created_tags << tag
      issuer.async_create_issue(tag) do |tag|
        program.save_tag_in_file(tag)
      end
    end
  end

  issuer.async_update_or_close_issues(issues, tags_by_issue_id) do
  |issue_id, tag, action|
    case action
    when :updated
      program.save_tag_in_file(tag)
      updated_tags << tag
    when :closed
      closed_issues << issue_id
    end
  end

  event_loop.wait_for_pending()

  if sourcer.respond_to? :finish
    sourcer.finish(created_tags, updated_tags, closed_issues)
  end
end

Instance Method Details

#classify_tags(tags) ⇒ Object


191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/issuesrc.rb', line 191

def classify_tags(tags)
  tags_by_issue = {}
  new_tags = []
  tags.each do |tag|
    if tag.issue_id.nil?
      new_tags << tag
    else
      tags_by_issue[tag.issue_id] = tag
    end
  end
  [tags_by_issue, new_tags]
end

#do_require(path) ⇒ Object


214
215
216
# File 'lib/issuesrc.rb', line 214

def do_require(path)
  require path
end

#init_files_offsetsObject


94
95
96
# File 'lib/issuesrc.rb', line 94

def init_files_offsets
  @files_offsets = {}
end

#load_component(config_key, arg_key, default, options) ⇒ Object


134
135
136
137
138
139
140
# File 'lib/issuesrc.rb', line 134

def load_component(config_key, arg_key, default, options)
  type = Config.option_from_both(arg_key, config_key, @args, @config)
  if type.nil?
    type = default
  end
  load_component_by_type(type, options)
end

#load_component_by_type(type, options) ⇒ Object


142
143
144
145
146
147
148
# File 'lib/issuesrc.rb', line 142

def load_component_by_type(type, options)
  if !options.include?(type)
    Issuesrc::exec_fail 'Unrecognized sourcer type: #{type}'
  end

  options[type]
end

#load_issuer(event_loop) ⇒ Object

Like `load_sourcer`, but for the issuer. It first looks at :issuer from the command line arguments, then `[issuer] issuer = …` from the config file.


120
121
122
123
124
125
126
127
128
# File 'lib/issuesrc.rb', line 120

def load_issuer(event_loop)
  path, cls = load_component(
    ['issuer', 'issuer'],
    :issuer,
    DEFAULT_ISSUER,
    ISSUERS)
  do_require(path)
  make_issuer(cls, event_loop)
end

#load_sourcerObject

Creates the instance of the sourcer that should be used for the current execution of issuesrc. It looks first at the :sourcer command line argument, then `[sourcer] sourcer = …` from the config file. If those are not present, `DEFAULT_SOURCER` will be used. If the selected sourcer is not implemented, ie. is not a key of `SOURCERS`, the execution will fail.


103
104
105
106
107
108
109
110
111
# File 'lib/issuesrc.rb', line 103

def load_sourcer
  path, cls = load_component(
    ['sourcer', 'sourcer'],
    :sourcer,
    DEFAULT_SOURCER,
    SOURCERS)
  do_require(path)
  make_sourcer(cls)
end

#load_tag_extractorObject


172
173
174
# File 'lib/issuesrc.rb', line 172

def load_tag_extractor
  Issuesrc::TagExtractor.new(@args, @config)
end

#load_tag_findersObject

Like `load_sourcer` but for the tag finders. It only looks at `[tag_finders] tag_finders = […]` from the config file.


152
153
154
155
156
157
158
159
# File 'lib/issuesrc.rb', line 152

def load_tag_finders
  tag_finders = Config.option_from_config(
    ['tag_finders', 'tag_finders'], @config)
  if tag_finders.nil?
    tag_finders = DEFAULT_TAG_FINDERS
  end
  load_tag_finders_by_types(tag_finders)
end

#load_tag_finders_by_types(types) ⇒ Object


161
162
163
164
165
166
167
168
169
170
# File 'lib/issuesrc.rb', line 161

def load_tag_finders_by_types(types)
  tag_extractor = load_tag_extractor()
  tag_finders = []
  types.each do |type|
    path, cls = load_component_by_type(type, TAG_FINDERS)
    do_require(path)
    tag_finders << make_tag_finder(cls, tag_extractor)
  end
  tag_finders
end

#make_issuer(cls, event_loop) ⇒ Object


130
131
132
# File 'lib/issuesrc.rb', line 130

def make_issuer(cls, event_loop)
  Issuesrc::Issuers.const_get(cls).new(@args, @config, event_loop)
end

#make_sourcer(cls) ⇒ Object


113
114
115
# File 'lib/issuesrc.rb', line 113

def make_sourcer(cls)
  Issuesrc::Sourcers.const_get(cls).new(@args, @config)
end

#make_tag_finder(cls, tag_extractor) ⇒ Object


176
177
178
# File 'lib/issuesrc.rb', line 176

def make_tag_finder(cls, tag_extractor)
  Issuesrc::TagFinders.const_get(cls).new(tag_extractor, @args, @config)
end

#save_tag_in_file(tag) ⇒ Object


204
205
206
207
208
# File 'lib/issuesrc.rb', line 204

def save_tag_in_file(tag)
  offsets = @files_offsets.fetch(tag.file.path, [])
  offsets = tag.write_in_file(offsets)
  @files_offsets[tag.file.path] = offsets
end

#select_tag_finder_for(file, tag_finders) ⇒ Object


180
181
182
183
184
185
186
187
188
189
# File 'lib/issuesrc.rb', line 180

def select_tag_finder_for(file, tag_finders)
  ret = nil
  tag_finders.each do |tag_finder|
    if tag_finder.accepts? file
      ret = tag_finder
      break
    end
  end
  ret
end

#set_config(args, config) ⇒ Object


87
88
89
90
# File 'lib/issuesrc.rb', line 87

def set_config(args, config)
  @args = args
  @config = config
end