ursm-ditz 0.4 → 0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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?