ursm-ditz 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/Changelog +15 -0
  2. data/INSTALL +20 -0
  3. data/LICENSE +674 -0
  4. data/Manifest.txt +40 -0
  5. data/PLUGINS.txt +140 -0
  6. data/README.txt +43 -27
  7. data/Rakefile +36 -3
  8. data/ReleaseNotes +6 -0
  9. data/bin/ditz +49 -63
  10. data/contrib/completion/ditz.bash +25 -9
  11. data/lib/ditz.rb +52 -7
  12. data/lib/ditz/file-storage.rb +54 -0
  13. data/lib/{hook.rb → ditz/hook.rb} +1 -1
  14. data/lib/{html.rb → ditz/html.rb} +42 -4
  15. data/lib/{lowline.rb → ditz/lowline.rb} +31 -11
  16. data/lib/{model-objects.rb → ditz/model-objects.rb} +53 -21
  17. data/lib/ditz/model.rb +321 -0
  18. data/lib/{operator.rb → ditz/operator.rb} +122 -67
  19. data/lib/ditz/plugins/git-sync.rb +83 -0
  20. data/lib/{plugins → ditz/plugins}/git.rb +57 -18
  21. data/lib/ditz/plugins/issue-claiming.rb +174 -0
  22. data/lib/ditz/plugins/issue-labeling.rb +161 -0
  23. data/lib/{util.rb → ditz/util.rb} +4 -0
  24. data/lib/{view.rb → ditz/view.rb} +0 -0
  25. data/lib/{views.rb → ditz/views.rb} +7 -4
  26. data/man/{ditz.1 → man1/ditz.1} +1 -1
  27. data/setup.rb +1585 -0
  28. data/share/ditz/blue-check.png +0 -0
  29. data/{lib → share/ditz}/component.rhtml +7 -5
  30. data/share/ditz/green-bar.png +0 -0
  31. data/share/ditz/green-check.png +0 -0
  32. data/share/ditz/index.rhtml +130 -0
  33. data/share/ditz/issue.rhtml +119 -0
  34. data/share/ditz/issue_table.rhtml +28 -0
  35. data/share/ditz/red-check.png +0 -0
  36. data/share/ditz/release.rhtml +98 -0
  37. data/share/ditz/style.css +226 -0
  38. data/share/ditz/unassigned.rhtml +23 -0
  39. data/share/ditz/yellow-bar.png +0 -0
  40. metadata +50 -28
  41. data/lib/index.rhtml +0 -113
  42. data/lib/issue.rhtml +0 -111
  43. data/lib/issue_table.rhtml +0 -33
  44. data/lib/model.rb +0 -208
  45. data/lib/plugins/issue-claiming.rb +0 -92
  46. data/lib/release.rhtml +0 -69
  47. data/lib/style.css +0 -127
  48. data/lib/trollop.rb +0 -518
  49. data/lib/unassigned.rhtml +0 -31
  50. data/lib/vendor/yaml_waml.rb +0 -28
@@ -0,0 +1,40 @@
1
+ Changelog
2
+ INSTALL
3
+ LICENSE
4
+ Manifest.txt
5
+ PLUGINS.txt
6
+ README.txt
7
+ Rakefile
8
+ ReleaseNotes
9
+ bin/ditz
10
+ contrib/completion/_ditz.zsh
11
+ contrib/completion/ditz.bash
12
+ lib/ditz.rb
13
+ lib/ditz/file-storage.rb
14
+ lib/ditz/hook.rb
15
+ lib/ditz/html.rb
16
+ lib/ditz/lowline.rb
17
+ lib/ditz/model-objects.rb
18
+ lib/ditz/model.rb
19
+ lib/ditz/operator.rb
20
+ lib/ditz/plugins/git-sync.rb
21
+ lib/ditz/plugins/git.rb
22
+ lib/ditz/plugins/issue-claiming.rb
23
+ lib/ditz/plugins/issue-labeling.rb
24
+ lib/ditz/util.rb
25
+ lib/ditz/view.rb
26
+ lib/ditz/views.rb
27
+ share/ditz/index.rhtml
28
+ share/ditz/issue.rhtml
29
+ share/ditz/issue_table.rhtml
30
+ share/ditz/release.rhtml
31
+ share/ditz/unassigned.rhtml
32
+ share/ditz/component.rhtml
33
+ share/ditz/style.css
34
+ share/ditz/blue-check.png
35
+ share/ditz/green-bar.png
36
+ share/ditz/green-check.png
37
+ share/ditz/red-check.png
38
+ share/ditz/yellow-bar.png
39
+ man/man1/ditz.1
40
+ setup.rb
@@ -0,0 +1,140 @@
1
+ Ditz plugin documentation
2
+ -------------------------
3
+
4
+ Ditz features a code plugin system for adding and extending commands, fields,
5
+ and output. Ditz's plugin system is used to add optional functionality to Ditz.
6
+
7
+ If you're interested in writing a plugin, look at the simple plugins in
8
+ lib/ditz/plugin/, and see
9
+ http://all-thing.net/2008/07/ditz-04-and-magic-of-ruby-dsls.html
10
+ If you're interested using plugins, read on.
11
+
12
+ Ditz loads specific plugins by looking for a .ditz-plugins file in the project
13
+ root. The format of this file is a YAML array of strings, where each string is
14
+ a plugin name. You can write this by hand like this:
15
+
16
+ - my-plugin
17
+ - another-plugin
18
+
19
+ I.e. one plugin name per line, prefixed by "- " as the first two characters of each line.
20
+
21
+ For each listed plugin name, Ditz looks for a file named
22
+ "lib/ditz/plugin/<name>.rb" within Ruby's default search path. Assuming Ditz is
23
+ installed in a standard manner, you should have available to you the following
24
+ shipped plugins:
25
+
26
+ 1. git
27
+ 2. git-sync
28
+ 3. issue-claiming
29
+ 4. issue-labeling
30
+
31
+ git
32
+ ---
33
+
34
+ This plugin allows issues to be associated with git commits and git
35
+ branches. Git commits can be easily tagged with a ditz issue with the 'ditz
36
+ commit' command, and both 'ditz show' and the ditz HTML output will then
37
+ contain a list of associated commits for each issue.
38
+
39
+ Issues can also be assigned a single git feature branch. In this case, all
40
+ commits on that branch will listed as commits for that issue. This
41
+ particular feature is fairly rudimentary, however---it assumes the reference
42
+ point is the 'master' branch, and once the feature branch is merged back
43
+ into master, the list of commits disappears.
44
+
45
+ Two configuration variables are added, which, when specified, are used to
46
+ construct HTML links for the git commit id and branch names in the generated
47
+ HTML output.
48
+
49
+ Commands added:
50
+ ditz set-branch: set the git branch of an issue
51
+ ditz commit: run git-commit, and insert the issue id into the commit
52
+ message.
53
+
54
+ Usage:
55
+ 1. add a line "- git" to the .ditz-plugins file in the project root
56
+ 2. run ditz reconfigure, and enter the URL prefixes, if any, from
57
+ which to create commit and branch links.
58
+ 3. use 'ditz commit' with abandon.
59
+
60
+ git-sync
61
+ --------
62
+
63
+ This plugin is useful for when you want synchronized, non-distributed issue
64
+ coordination with other developers, and you're using git. It allows you to
65
+ synchronize issue updates with other developers by using the 'ditz sync'
66
+ command, which does all the git work of sending and receiving issue change
67
+ for you. However, you have to set things up in a very specific way for this
68
+ to work:
69
+
70
+ 1. Your ditz state must be on a separate branch. I recommend calling it
71
+ 'bugs'. Create this branch, do a ditz init, and push it to the remote
72
+ repo. (This means you won't be able to mingle issue change and code
73
+ change in the same commits. If you care.)
74
+ 2. Make a checkout of the bugs branch in a separate directory, but NOT in
75
+ your code checkout. If you're developing in a directory called "project",
76
+ I recommend making a ../project-bugs/ directory, cloning the repo there
77
+ as well, and keeping that directory checked out to the 'bugs' branch.
78
+ (There are various complicated things you can do to make that directory
79
+ share git objects with your code directory, but I wouldn't bother unless
80
+ you really care about disk space. Just make it an independent clone.)
81
+ 3. Set that directory as your issue-dir in your .ditz-config file in your
82
+ code checkout directory. (This file should be in .gitignore, btw.)
83
+ 4. Run 'ditz reconfigure' and fill in the local branch name, remote
84
+ branch name, and remote repo for the issue tracking branch.
85
+
86
+ Once that's set up, 'ditz sync' will change to the bugs checkout dir, bundle
87
+ up any changes you've made to issue status, push them to the remote repo,
88
+ and pull any new changes in too. All ditz commands will read from your bugs
89
+ directory, so you should be able to use ditz without caring about where
90
+ things are anymore.
91
+
92
+ This complicated setup is necessary to avoid accidentally mingling code
93
+ change and issue change. With this setup, issue change is synchronized,
94
+ but how you synchronize code is still up to you.
95
+
96
+ Usage:
97
+ 0. read all the above text very carefully
98
+ 1. add a line "- git-sync" to the .ditz-plugins file in the project
99
+ root
100
+ 2. run 'ditz reconfigure' and answer its questions
101
+ 3. run 'ditz sync' with abandon
102
+
103
+ issue-claiming
104
+ --------------
105
+
106
+ This plugin allows people to claim issues. This is useful for avoiding
107
+ duplication of work---you can check to see if someone's claimed an
108
+ issue before starting to work on it, and you can let people know what
109
+ you're working on.
110
+
111
+ Commands added:
112
+ ditz claim: claim an issue for yourself
113
+ ditz unclaim: unclaim a claimed issue
114
+ ditz mine: show all issues claimed by you
115
+ ditz claimed: show all claimed issues, by developer
116
+ ditz unclaimed: show all unclaimed issues
117
+
118
+ Usage:
119
+ 1. add a line "- issue-claiming" to the .ditz-plugins file in the project
120
+ root
121
+ 2. use the above commands to abandon
122
+
123
+ issue-labeling
124
+ --------------
125
+
126
+ This plugin allows label issues. This can replace the issue component
127
+ and/or issue types (bug,feature,task), by providing a more flexible
128
+ to organize your issues.
129
+
130
+ Commands added:
131
+ ditz new_label [label]: create a new label for the project
132
+ ditz label <issue> <labels>: label an issue with some labels
133
+ ditz unlabel <issue> [labels]: remove some label(s) of an issue
134
+ ditz labeled <labels> [release]: show all issues with these labels
135
+
136
+ Usage:
137
+ 1. add a line "- issue-labeling" to the .ditz-plugins file in the project
138
+ root
139
+ 2. use the above commands to abandon
140
+
data/README.txt CHANGED
@@ -14,7 +14,18 @@ Ditz maintains an issue database directory on disk, with files written in a
14
14
  line-based and human-editable format. This directory can be kept under version
15
15
  control, alongside project code.
16
16
 
17
- There are several different ways to use ditz:
17
+ Ditz provides a simple, console-based interface for creating and updating the
18
+ issue database files, and some basic static HTML generation capabilities for
19
+ producing world-readable status pages (for a demo, see the ditz ditz page).
20
+
21
+ Ditz includes a robust plugin system for adding commands, model fields, and
22
+ modifying output. See PLUGINS.txt for documentation on the pre-shipped plugins.
23
+
24
+ Ditz currently offers no central public method of bug submission.
25
+
26
+ == USING DITZ
27
+
28
+ There are several different ways to use Ditz:
18
29
 
19
30
  1. Treat issue change the same as code change: include it as part of commits,
20
31
  and merge it with changes from other developers, resolving conflicts in the
@@ -24,12 +35,18 @@ There are several different ways to use ditz:
24
35
  commits.
25
36
  3. Keep the issue database separate and not under VCS at all.
26
37
 
27
- Ditz provides a simple, console-based interface for creating and updating the
28
- issue database file, and some rudimentary static HTML generation capabilities
29
- for producing world-readable status pages (for a demo, see the ditz ditz page).
30
- It currently offers no central public method of bug submission.
38
+ All of these options are supported; the choice of which to use depends on your
39
+ workflow.
40
+
41
+ Option #1 is probably most appropriate for the unsynchronized, distributed
42
+ development, since it allows individual developers to modify issue state with a
43
+ minimum of hassle. Option #2 is most suitable for synchronized development, as
44
+ issue state change can be transmitted independently of code change (see also
45
+ the git-sync plugin) and can act as a sychronization mechanism. Option #3 is
46
+ only useful with some other distribution mechanism, like a central web
47
+ interface.
31
48
 
32
- == SYNOPSIS
49
+ == COMMANDLINE SYNOPSIS
33
50
 
34
51
  # set up project. creates the bugs.yaml file.
35
52
  1. ditz init
@@ -53,16 +70,17 @@ It currently offers no central public method of bug submission.
53
70
 
54
71
  == THE DITZ DATA MODEL
55
72
 
56
- Ditz includes the bare minimum set of features necessary for open-source
57
- development. Features like time spent, priority, assignment of tasks to
58
- developers, due dates, etc. are purposely excluded.
73
+ By default, Ditz includes the bare minimum set of features necessary for
74
+ open-source development. Features like time spent, priority, assignment of
75
+ tasks to developers, due dates, etc. are purposely relegated to the plugin
76
+ system.
59
77
 
60
- A ditz project consists of issues, releases and components.
78
+ A Ditz project consists of issues, releases and components.
61
79
 
62
80
  Issues:
63
- Issues are the fundamental currency of issue tracking. A ditz issue is either
64
- a feature or a bug, but this distinction doesn't affect anything other than
65
- how they're displayed.
81
+ Issues are the fundamental currency of issue tracking. A Ditz issue is either
82
+ a feature or a bug, but this distinction currently doesn't affect anything
83
+ other than how they're displayed.
66
84
 
67
85
  Each issue belongs to exactly one component, and is part of zero or one
68
86
  releases.
@@ -72,9 +90,13 @@ Issues:
72
90
  developers, present and future. Issue ids are typically not exposed to the
73
91
  user.
74
92
 
75
- Issues also have a non-exportable name, which is short and human-readable.
76
- All ditz commands use issue names instead of issue ids. Issue ids may change
77
- in certain circumstances, specifically after a "ditz drop" command.
93
+ Issues also have a non-global, non-exportable name, which is short and
94
+ human-readable. All Ditz commands use issue names in addition to issue ids.
95
+ Issue names (but not issue ids) may change in certain circumstances, e.g.
96
+ after a "ditz drop" command.
97
+
98
+ Issue names can be specified in comments, titles and descriptions, and Ditz
99
+ will automatically rewrite them as necessary when they change.
78
100
 
79
101
  Components:
80
102
  There is always one "general" component, named after the project itself. In
@@ -82,20 +104,14 @@ Components:
82
104
  with the question of which component to assign an issue to.
83
105
 
84
106
  Components simply provide a way of organizing issues, and have no real
85
- functionality. Issues are assigned names derived form the component they're
86
- assigned to.
107
+ functionality. Issues names are derived from the component they're assigned
108
+ to.
87
109
 
88
110
  Releases:
89
111
  A release is the primary grouping mechanism for issues. Status commands like
90
112
  "ditz status" and "ditz todo" always group issues by release. When a release
91
- is 100% complete, it can be marked as released, in which case the associated
92
- issues will cease appearing in ditz status and todo messages.
93
-
94
- == FUTURE WORK
95
-
96
- In future releases, Ditz will have a plugin architecture to allow tighter
97
- integration with specific SCMs and developer communication channels. (See
98
- http://ditz.rubyforge.org/ditz/issue-0704dafe4aef96279364013aba177a0971d425cb.html)
113
+ is 100% complete, it can be marked as released, and its issues will cease
114
+ appearing in Ditz status and todo messages.
99
115
 
100
116
  == LEARNING MORE
101
117
 
@@ -104,7 +120,7 @@ http://ditz.rubyforge.org/ditz/issue-0704dafe4aef96279364013aba177a0971d425cb.ht
104
120
 
105
121
  == REQUIREMENTS
106
122
 
107
- * trollop >= 1.8.2
123
+ * trollop >= 1.8.2, if running via RubyGems.
108
124
 
109
125
  == INSTALLATION
110
126
 
data/Rakefile CHANGED
@@ -5,8 +5,8 @@ $:.unshift "lib"
5
5
  require 'ditz'
6
6
 
7
7
  class Hoe
8
- def extra_deps; @extra_deps.reject { |x| Array(x).first == "hoe" } end
9
- end # thanks to "Mike H"
8
+ def extra_dev_deps; @extra_dev_deps.reject { |x| x[0] == "hoe" } end
9
+ end
10
10
 
11
11
  Hoe.new('ditz', Ditz::VERSION) do |p|
12
12
  p.rubyforge_name = 'ditz'
@@ -17,9 +17,10 @@ Hoe.new('ditz', Ditz::VERSION) do |p|
17
17
  p.url = "http://ditz.rubyforge.org"
18
18
  p.changes = p.paragraphs_of('Changelog', 0..0).join("\n\n")
19
19
  p.email = "wmorgan-ditz@masanjin.net"
20
+ p.extra_deps = [['trollop', '>= 1.9'], ['kakutani-yaml_waml', '>= 0.3']]
20
21
  end
21
22
 
22
- WWW_FILES = FileList["www/*"] + %w(README.txt)
23
+ WWW_FILES = FileList["www/*"] + %w(README.txt PLUGINS.txt)
23
24
 
24
25
  task :upload_webpage => WWW_FILES do |t|
25
26
  sh "rsync -essh -cavz #{t.prerequisites * ' '} wmorgan@rubyforge.org:/var/www/gforge-projects/ditz/"
@@ -30,4 +31,36 @@ task :upload_report do |t|
30
31
  sh "rsync -essh -cavz ditz wmorgan@rubyforge.org:/var/www/gforge-projects/ditz/"
31
32
  end
32
33
 
34
+ task :plugins do |t|
35
+ sh "ruby -w ./make-plugins.txt.rb > PLUGINS.txt"
36
+ end
37
+
38
+ task :really_check_manifest do |t|
39
+ f1 = Tempfile.new "manifest"; f1.close
40
+ f2 = Tempfile.new "manifest"; f2.close
41
+ sh "git ls-files | egrep -v \"^bugs/\" | sort > #{f1.path}"
42
+ sh "sort Manifest.txt > #{f2.path}"
43
+
44
+ f3 = Tempfile.new "manifest"; f3.close
45
+ sh "diff -u #{f1.path} #{f2.path} > #{f3.path}; /bin/true"
46
+
47
+ left, right = [], []
48
+ IO.foreach(f3.path) do |l|
49
+ case l
50
+ when /^\-\-\-/
51
+ when /^\+\+\+/
52
+ when /^\-(.*)\n$/; left << $1
53
+ when /^\+(.*)\n$/; right << $2
54
+ end
55
+ end
56
+
57
+ puts
58
+ puts "Tracked by git but not in Manifest.txt:"
59
+ puts left.empty? ? " <nothing>" : left.map { |l| " " + l }
60
+
61
+ puts
62
+ puts "In Manifest.txt, but not tracked by git:"
63
+ puts right.empty? ? " <nothing>" : right.map { |l| " " + l }
64
+ end
65
+
33
66
  # vim: syntax=ruby
@@ -1,3 +1,9 @@
1
+ 0.5
2
+ ---
3
+
4
+ Two new plugins: git-sync, for synchronized git usage, and issue-claiming,
5
+ which allows you to claim issues for yourself. See PLUGINS.txt for details.
6
+
1
7
  0.4
2
8
  ---
3
9
  - Command-line completion scripts are now included for bash and zsh. To
data/bin/ditz CHANGED
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/ruby1.8
2
2
 
3
+ $LOAD_PATH.unshift(File.expand_path("#{File.dirname($0)}/../lib"))
4
+
3
5
  ## requires are split in two for efficiency reasons: ditz should be really
4
6
  ## fast when using it for completion.
5
7
  $KCODE = "u"
6
8
 
7
- require 'operator'
9
+ require 'ditz/operator'
8
10
  op = Ditz::Operator.new
9
11
 
10
12
  ## a secret option for shell completion
@@ -13,14 +15,19 @@ if ARGV.include? '--commands'
13
15
  exit 0
14
16
  end
15
17
 
16
- require 'rubygems' rescue LoadError nil
18
+ begin
19
+ require 'rubygems'
20
+ # list version dependant gems here.
21
+ gem 'kakutani-yaml_waml', '>= 0.3'
22
+ gem 'trollop', '>= 1.9'
23
+ rescue LoadError
24
+ end
25
+
17
26
  require 'fileutils'
18
27
  require 'pathname'
19
28
  require 'trollop'; include Trollop
20
29
  require "ditz"
21
- require "vendor/yaml_waml"
22
30
 
23
- PROJECT_FN = "project.yaml"
24
31
  CONFIG_FN = ".ditz-config"
25
32
  PLUGIN_FN = ".ditz-plugins"
26
33
 
@@ -33,10 +40,10 @@ $opts = options do
33
40
  opt :config_file, "Configuration file", :default => File.join(config_dir || ".", CONFIG_FN)
34
41
  opt :plugins_file, "Plugins file", :default => File.join(plugin_dir || ".", PLUGIN_FN)
35
42
  opt :verbose, "Verbose output", :default => false
36
- opt :no_comment, "Skip asking for a comment", :default => false
37
43
  opt :list_hooks, "List all hooks and descriptions, and quit.", :short => 'l', :default => false
38
44
  stop_on_unknown
39
45
  end
46
+ $verbose = true if $opts[:verbose]
40
47
 
41
48
  Ditz::HookManager.register :startup, <<EOS
42
49
  Executes at startup
@@ -77,18 +84,10 @@ if $opts[:list_hooks]
77
84
  exit 0
78
85
  end
79
86
 
80
- plugins = begin
81
- Ditz::debug "loading plugins from #{$opts[:plugins_file]}"
82
- YAML::load_file$opts[:plugins_file]
87
+ begin
88
+ Ditz::load_plugins $opts[:plugins_file]
83
89
  rescue SystemCallError => e
84
90
  Ditz::debug "can't load plugins file: #{e.message}"
85
- []
86
- end
87
-
88
- plugins.each do |p|
89
- fn = Ditz::find_ditz_file "plugins/#{p}.rb"
90
- Ditz::debug "loading plugin #{p.inspect} from #{fn}"
91
- load fn
92
91
  end
93
92
 
94
93
  config = begin
@@ -109,49 +108,40 @@ EOS
109
108
  end
110
109
  end
111
110
 
112
- cmd = ARGV.shift || "todo"
113
111
  issue_dir = Pathname.new(config.issue_dir || $opts[:issue_dir])
112
+ cmd = ARGV.shift || "todo"
113
+ unless op.has_operation? cmd
114
+ die "no such command: #{cmd}"
115
+ end
114
116
 
115
117
  case cmd # some special commands not handled by Ditz::Operator
116
118
  when "init"
117
119
  die "#{issue_dir} directory already exists" if issue_dir.exist?
118
120
  issue_dir.mkdir
119
- fn = issue_dir + PROJECT_FN
121
+ fn = issue_dir + Ditz::FileStorage::PROJECT_FN
120
122
  project = op.init
121
123
  project.save! fn
122
124
  puts "Ok, #{issue_dir} directory created successfully."
123
125
  exit
126
+ when "reconfigure" # might not be able to load the project
127
+ op.do cmd, nil, config, ARGV
128
+ exit
124
129
  when "help"
125
- op.do "help", nil, nil, ARGV
130
+ op.do cmd, nil, nil, ARGV
126
131
  exit
127
132
  end
128
133
 
129
- project_root = Ditz::find_dir_containing(issue_dir + PROJECT_FN)
130
- die "No #{issue_dir} directory---use 'ditz init' to initialize" unless project_root
131
- project_root += issue_dir
134
+ $project_root = Ditz::find_dir_containing(issue_dir + Ditz::FileStorage::PROJECT_FN)
135
+ die "No #{issue_dir} directory---use 'ditz init' to initialize" unless $project_root
136
+ $project_root += issue_dir
132
137
 
138
+ storage = Ditz::FileStorage.new $project_root
133
139
  project = begin
134
- fn = project_root + PROJECT_FN
135
- Ditz::debug "loading project from #{fn}"
136
- project = Ditz::Project.from fn
137
-
138
- fn = project_root + "issue-*.yaml"
139
- Ditz::debug "loading issues from #{fn}"
140
- project.issues = Dir[fn].map { |fn| Ditz::Issue.from fn }
141
- Ditz::debug "found #{project.issues.size} issues"
142
- project
140
+ storage.load
143
141
  rescue SystemCallError, Ditz::Project::Error => e
144
142
  die "#{e.message} (use 'init' to initialize)"
145
143
  end
146
144
 
147
- project.validate!
148
- project.issues.each { |p| p.project = project}
149
- project.assign_issue_names!
150
-
151
- unless op.has_operation? cmd
152
- die "no such command: #{cmd}"
153
- end
154
-
155
145
  Ditz::HookManager.run :startup, project, config
156
146
 
157
147
  Ditz::debug "executing command #{cmd}"
@@ -165,47 +155,43 @@ rescue Errno::EPIPE, Interrupt
165
155
  exit 1
166
156
  end
167
157
 
168
- ## save project.yaml
169
- dirty = project.each_modelobject { |o| break true if o.changed? } || false
170
- if dirty
171
- fn = project_root + PROJECT_FN
172
- Ditz::debug "project is dirty, saving #{fn}"
173
- project.save! fn
174
- end
175
-
176
- ## project issues are not model fields proper, so they must be
177
- ## saved independently.
178
158
  changed_issues = project.issues.select { |i| i.changed? }
179
- changed_issues.each do |i|
180
- i.pathname ||= (project_root + "issue-#{i.id}.yaml")
181
- i.project ||= project # hack: not set on new issues
182
- Ditz::debug "issue #{i.name} is dirty, saving #{i.pathname}"
183
- i.save! i.pathname
184
- end
159
+ changed_not_added_issues = changed_issues - project.added_issues
185
160
 
186
- project.deleted_issues.each do |i|
187
- fn = i.pathname
188
- Ditz::debug "issue #{i.name} has been deleted, deleting #{fn}"
189
- FileUtils.rm fn
190
- end
161
+ storage.save project
162
+
163
+ ## at this point, for compatibility with older hook stuff, we set the pathname
164
+ ## directly on the issues.
191
165
 
166
+ project.issues.each { |i| i.pathname = storage.filename_for_issue(i) }
192
167
  unless project.added_issues.empty?
193
168
  unless Ditz::HookManager.run :after_add, project, config, project.added_issues
194
169
  puts "You may have to inform your SCM that the following files have been added:"
195
- project.added_issues.each { |i| puts " " + i.pathname }
170
+ project.added_issues.each { |i| puts " " + storage.filename_for_issue(i) }
196
171
  end
197
172
  end
198
173
 
199
174
  unless project.deleted_issues.empty?
200
175
  unless Ditz::HookManager.run :after_delete, project, config, project.deleted_issues
201
176
  puts "You may have to inform your SCM that the following files have been deleted:"
202
- project.deleted_issues.each { |i| puts " " + i.pathname }
177
+ project.deleted_issues.each { |i| puts " " + storage.filename_for_issue(i) }
203
178
  end
204
179
  end
205
180
 
206
- changed_not_added_issues = changed_issues - project.added_issues
207
181
  unless changed_not_added_issues.empty?
208
- Ditz::HookManager.run :after_update, project, config, changed_not_added_issues
182
+ unless Ditz::HookManager.run :after_update, project, config, changed_not_added_issues
183
+ puts "You may have to inform your SCM that the following files have been modified:"
184
+ changed_not_added_issues.each { |i| puts " " + storage.filename_for_issue(i) }
185
+ end
186
+ end
187
+
188
+ ## hack upon a hack
189
+ if project.changed?
190
+ project.pathname = storage.filename_for_project
191
+ unless Ditz::HookManager.run :after_update, project, config, [project]
192
+ puts "You may have to inform your SCM that the following files have been modified:"
193
+ puts " " + storage.filename_for_project
194
+ end
209
195
  end
210
196
 
211
197
  config.save! $opts[:config_file] if config.changed?