Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fixed some bugs in your issues code #1

Closed
wants to merge 10 commits into from

2 participants

@pwnall

I also rebased your code against master, so you'll have to redo your branch.

git fetch pwnall
git checkout pwnall/issues
git branch -D dev
git checkout -b dev
pwnall and others added some commits
@pwnall pwnall Updated to Rails 3.2.2. 0188cb1
@pwnall pwnall Added config var for disabling syntax highlighting, because the featu…
…re isn't fully baked.
44a8693
@pwnall pwnall Added CSRF to config vars layout. d9abece
@pwnall pwnall Merge pull request #6 from christy13/master
E-mail addresses are allowed to contain hyphens
13b2250
@pwnall pwnall Silenced git during the integration test. 65a842d
@pwnall pwnall Rails 3.2.3 and better git user creation. fea3ad9
@christydennison Feed items do not display correctly, with error `can't convert Symbol…
… into Integer' for line 102 of views/feed_items/_feed_item.html.erb.

Issues cannot be shown once created with error `undefined method `can_edit?' for nil:NilClass' in line 26 of views/issues/_open.html.erb, even though the debug statements indicate that the object `issue' is not nil.
c510f9e
@pwnall pwnall Model cleanup for the issues feature. a8971f5
@pwnall pwnall Fixed some controller issues and all tests. 69e8411
@pwnall pwnall Removed unnecessary files. 8c3dced
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 6, 2012
  1. @pwnall

    Updated to Rails 3.2.2.

    pwnall authored
Commits on Mar 12, 2012
  1. @pwnall
Commits on Mar 13, 2012
  1. @pwnall
  2. @pwnall

    Merge pull request #6 from christy13/master

    pwnall authored
    E-mail addresses are allowed to contain hyphens
  3. @pwnall
Commits on Apr 1, 2012
  1. @pwnall
  2. @pwnall

    Feed items do not display correctly, with error `can't convert Symbol…

    authored pwnall committed
    … into Integer' for line 102 of views/feed_items/_feed_item.html.erb.
    
    Issues cannot be shown once created with error `undefined method `can_edit?' for nil:NilClass' in line 26 of views/issues/_open.html.erb, even though the debug statements indicate that the object `issue' is not nil.
  3. @pwnall
  4. @pwnall
  5. @pwnall

    Removed unnecessary files.

    pwnall authored
This page is out of date. Refresh to see the latest.
Showing with 663 additions and 55 deletions.
  1. +1 −0  .project
  2. +43 −43 Gemfile.lock
  3. +5 −0 README.md
  4. +1 −1  app/assets/stylesheets/fonts.css.scss
  5. +4 −1 app/assets/stylesheets/markdpwn.css.scss
  6. +104 −0 app/controllers/issues_controller.rb
  7. +6 −2 app/helpers/blobs_helper.rb
  8. +2 −0  app/helpers/issues_helper.rb
  9. +2 −2 app/models/feed_item.rb
  10. +71 −0 app/models/issue.rb
  11. +4 −0 app/models/profile.rb
  12. +3 −0  app/models/repository.rb
  13. +20 −0 app/views/feed_items/_feed_item.html.erb
  14. +38 −0 app/views/issues/_closed.html.erb
  15. +25 −0 app/views/issues/_form.html.erb
  16. +39 −0 app/views/issues/_open.html.erb
  17. +8 −0 app/views/issues/edit.html.erb
  18. +11 −0 app/views/issues/index.html.erb
  19. +5 −0 app/views/issues/new.html.erb
  20. +32 −0 app/views/issues/show.html.erb
  21. +2 −0  app/views/layouts/config_vars.html.erb
  22. +4 −0 app/views/repositories/_repository.html.erb
  23. +1 −0  config/initializers/config_vars.rb
  24. +15 −1 config/routes.rb
  25. +16 −0 db/migrate/20120304034951_create_issues.rb
  26. +14 −1 db/schema.rb
  27. +20 −0 script/git_user/setup
  28. +6 −0 test/fixtures/issues.yml
  29. +66 −0 test/functional/issues_controller_test.rb
  30. +4 −4 test/integration/git_push_test.rb
  31. +11 −0 test/unit/helpers/blobs_helper_test.rb
  32. +4 −0 test/unit/helpers/comments_helper_test.rb
  33. +4 −0 test/unit/helpers/issues_helper_test.rb
  34. +72 −0 test/unit/issue_test.rb
View
1  .project
@@ -13,5 +13,6 @@
</buildSpec>
<natures>
<nature>org.radrails.rails.core.railsnature</nature>
+ <nature>com.aptana.ruby.core.rubynature</nature>
</natures>
</projectDescription>
View
86 Gemfile.lock
@@ -12,31 +12,31 @@ GEM
remote: http://rubygems.org/
specs:
RedCloth (4.2.9)
- actionmailer (3.2.2.rc1)
- actionpack (= 3.2.2.rc1)
- mail (~> 2.4.0)
- actionpack (3.2.2.rc1)
- activemodel (= 3.2.2.rc1)
- activesupport (= 3.2.2.rc1)
+ actionmailer (3.2.3)
+ actionpack (= 3.2.3)
+ mail (~> 2.4.4)
+ actionpack (3.2.3)
+ activemodel (= 3.2.3)
+ activesupport (= 3.2.3)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.1)
rack (~> 1.4.0)
- rack-cache (~> 1.1)
+ rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.1.2)
- activemodel (3.2.2.rc1)
- activesupport (= 3.2.2.rc1)
+ activemodel (3.2.3)
+ activesupport (= 3.2.3)
builder (~> 3.0.0)
- activerecord (3.2.2.rc1)
- activemodel (= 3.2.2.rc1)
- activesupport (= 3.2.2.rc1)
+ activerecord (3.2.3)
+ activemodel (= 3.2.3)
+ activesupport (= 3.2.3)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
- activeresource (3.2.2.rc1)
- activemodel (= 3.2.2.rc1)
- activesupport (= 3.2.2.rc1)
- activesupport (3.2.2.rc1)
+ activeresource (3.2.3)
+ activemodel (= 3.2.3)
+ activesupport (= 3.2.3)
+ activesupport (3.2.3)
i18n (~> 0.6)
multi_json (~> 1.0)
addressable (2.2.7)
@@ -53,8 +53,8 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.2.0)
- configvars_rails (0.5.2)
- rails (>= 3.2.0.rc2)
+ configvars_rails (0.5.3)
+ rails (>= 3.2.0)
creole (0.4.2)
daemons (1.1.8)
diff-lcs (1.1.3)
@@ -88,12 +88,12 @@ GEM
hike (1.2.1)
i18n (0.6.0)
journey (1.0.3)
- jquery-rails (2.0.0)
- railties (>= 3.2.0.beta, < 5.0)
+ jquery-rails (2.0.1)
+ railties (>= 3.2.0, < 5.0)
thor (~> 0.14)
- json (1.6.5)
+ json (1.6.6)
libv8 (3.3.10.4)
- mail (2.4.1)
+ mail (2.4.4)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
@@ -106,10 +106,10 @@ GEM
redcarpet (>= 2.1.0)
wikicloth (>= 0.7.1)
metaclass (0.0.1)
- mime-types (1.17.2)
- mocha (0.10.4)
+ mime-types (1.18)
+ mocha (0.10.5)
metaclass (~> 0.0.1)
- multi_json (1.1.0)
+ multi_json (1.2.0)
multipart-post (1.1.5)
mysql2 (0.3.11)
net-ssh (2.3.0)
@@ -118,27 +118,27 @@ GEM
multi_json (~> 1.0)
polyglot (0.3.3)
posix-spawn (0.3.6)
- pygments.rb (0.2.4)
+ pygments.rb (0.2.8)
rubypython (~> 0.5.3)
rack (1.4.1)
- rack-cache (1.1)
+ rack-cache (1.2)
rack (>= 0.4)
rack-ssl (1.3.2)
rack
rack-test (0.6.1)
rack (>= 1.0)
- railroady (1.0.6)
- rails (3.2.2.rc1)
- actionmailer (= 3.2.2.rc1)
- actionpack (= 3.2.2.rc1)
- activerecord (= 3.2.2.rc1)
- activeresource (= 3.2.2.rc1)
- activesupport (= 3.2.2.rc1)
+ railroady (1.0.7)
+ rails (3.2.3)
+ actionmailer (= 3.2.3)
+ actionpack (= 3.2.3)
+ activerecord (= 3.2.3)
+ activeresource (= 3.2.3)
+ activesupport (= 3.2.3)
bundler (~> 1.0)
- railties (= 3.2.2.rc1)
- railties (3.2.2.rc1)
- actionpack (= 3.2.2.rc1)
- activesupport (= 3.2.2.rc1)
+ railties (= 3.2.3)
+ railties (3.2.3)
+ actionpack (= 3.2.3)
+ activesupport (= 3.2.3)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
@@ -148,14 +148,14 @@ GEM
rbtree-pure (0.1.1)
rdoc (3.12)
json (~> 1.4)
- redcarpet (2.1.0)
+ redcarpet (2.1.1)
rest-client (1.6.7)
mime-types (>= 1.16)
rubypython (0.5.3)
blankslate (>= 2.1.2.3)
ffi (~> 1.0.7)
sass (3.1.15)
- sass-rails (3.2.4)
+ sass-rails (3.2.5)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
@@ -164,7 +164,7 @@ GEM
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.5)
- therubyracer (0.9.10)
+ therubyracer (0.10.0)
libv8 (~> 3.3.10)
thin (1.3.1)
daemons (>= 1.0.9)
@@ -176,8 +176,8 @@ GEM
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
- tzinfo (0.3.31)
- uglifier (1.2.3)
+ tzinfo (0.3.32)
+ uglifier (1.2.4)
execjs (>= 0.3.0)
multi_json (>= 1.0.2)
wikicloth (0.7.1)
View
5 README.md
@@ -27,6 +27,11 @@ sudo apt-get install -y git libmysqlclient-dev libssl-dev mysql-client mysql-ser
On OSX, go to System Preferences > Sharing, check the Remote Login option.
+Gitty uses [markdpwn](https://github.com/pwnall/markdpwn) for source code
+highlighting, which has its own dependencies. If you can't get markdpwn's
+dependencies installed, set the `markdpwn` config var to `disabled`. (The
+section below describes config vars.)
+
## Installation
View
2  app/assets/stylesheets/fonts.css.scss
@@ -48,6 +48,6 @@ footer {
line-height: 1.12em;
}
-pre, div.markdpwn-parsed-code {
+pre, div.markdpwn-off-code, div.markdpwn-parsed-code {
font-family: "Droid Sans Mono";
}
View
5 app/assets/stylesheets/markdpwn.css.scss
@@ -48,12 +48,15 @@ $pre-color: $base1 !default;
// Code highlighting for solarized.
-div.markdpwn-parsed-code {
+div.markdpwn-off-code, div.markdpwn-parsed-code {
padding: 0.5em 0.5em;
line-height: 1.45em;
background: $pre-bg;
color: $pre-color;
white-space: pre;
+}
+
+div.markdpwn-parsed-code {
span { color: $pre-color; }
span { font-style: normal; font-weight: normal; }
View
104 app/controllers/issues_controller.rb
@@ -0,0 +1,104 @@
+class IssuesController < ApplicationController
+ # GET /issues
+ # GET /issues.json
+ def index
+ #@issues = Repository.find(params[:repo_name]).issues
+ @issues = Issue.all
+ Rails.logger.debug "Index issues: #{@issues.inspect}"
+
+ respond_to do |format|
+ format.html # index.html.erb
+ format.json { render json: @issues }
+ end
+ end
+
+ # GET /issues/1
+ # GET /issues/1.json
+ def show
+ @issue = Issue.find(params[:id])
+
+ respond_to do |format|
+ format.html # show.html.erb
+ format.json { render json: @issue }
+ end
+ end
+
+ # GET /issues/new
+ # GET /issues/new.json
+ def new
+ @profile = Profile.where(:name => params[:profile_name]).first
+ @repository = @profile.repositories.where(:name => params[:repo_name]).first
+
+ @issue = Issue.new
+ @issue.repository = @repository
+
+ respond_to do |format|
+ format.html # new.html.erb
+ format.json { render json: @issue }
+ end
+ end
+
+ # GET /issues/1/edit
+ def edit
+ @issue = Issue.find(params[:id])
+ end
+
+ # POST /issues
+ # POST /issues.json
+ def create
+ @author = current_user.profile
+ @profile = Profile.where(:name => params[:profile_name]).first
+ @repository = @profile.repositories.where(:name => params[:repo_name]).first
+
+ @issue = Issue.new params[:issue]
+ @issue.repository = @repository
+ @issue.author = @author
+
+ respond_to do |format|
+ if @issue.save
+ @issue.publish_creation
+ FeedSubscription.add @author, @issue
+
+ format.html { redirect_to profile_repository_issues_path(@profile,
+ @repository),
+ notice: 'Issue was successfully created.' }
+ format.json { render json: @issue, status: :created, location: @issue }
+ else
+ format.html { render action: "new" }
+ format.json { render json: @issue.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # PUT /issues/1
+ # PUT /issues/1.json
+ def update
+ @issue = Issue.find(params[:id])
+
+ respond_to do |format|
+ if @issue.update_attributes(params[:issue])
+ format.html { redirect_to profile_repository_issues_path(@profile,
+ @repository),
+ notice: 'Issue was successfully updated.' }
+ format.json { head :no_content }
+ else
+ format.html { render action: "edit" }
+ format.json { render json: @issue.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /issues/1
+ # DELETE /issues/1.json
+ def destroy
+ @issue = Issue.find(params[:id])
+ @issue.destroy
+ @issue.publish_deletion current_user.profile
+
+ respond_to do |format|
+ format.html { redirect_to profile_repository_issues_path(@profile,
+ @repository) }
+ format.json { head :no_content }
+ end
+ end
+end
View
8 app/helpers/blobs_helper.rb
@@ -15,7 +15,11 @@ def raw_blob_path(blob_ref, path)
# HTML representation of a blob contents.
def marked_up_blob(blob, blob_path)
- Markdpwn.markup(blob.data, :file_name => blob_path,
- :mime_type => blob.mime_type).html_safe
+ if ConfigVar['markdpwn'] == 'enabled'
+ Markdpwn.markup(blob.data, :file_name => blob_path,
+ :mime_type => blob.mime_type).html_safe
+ else
+ content_tag :div, html_escape(blob.data), :class => 'markdpwn-off-code'
+ end
end
end
View
2  app/helpers/issues_helper.rb
@@ -0,0 +1,2 @@
+module IssuesHelper
+end
View
4 app/models/feed_item.rb
@@ -32,8 +32,8 @@ def topics(reload = false)
# Valid actions.
def self.verbs
- %w(new_repository new_branch new_tag del_repository del_branch del_tag
- move_branch move_tag subscribe unsubscribe)
+ %w(new_repository new_branch new_tag new_issue del_repository del_branch
+ del_tag del_issue move_branch move_tag subscribe unsubscribe)
end
validates_inclusion_of :verb, :in => verbs
View
71 app/models/issue.rb
@@ -0,0 +1,71 @@
+# Entity that needs to be tracked (e.g. bug or feature) associated with a repo.
+class Issue < ActiveRecord::Base
+ # The repository that this issue refers to.
+ belongs_to :repository, :inverse_of => :issues
+ validates :repository, :presence => true
+
+ # The profile of the user who opened this issue.
+ belongs_to :author, :class_name => 'Profile', :inverse_of => :issues
+ validates :author, :presence => true
+
+ # One-line summary of the issue.
+ validates :title, :length => 1..160, :presence => true
+
+ # Full description of the issue, including repro steps, desired behavior, etc.
+ validates :description, :length => { :maximum => 1.kilobyte },
+ :exclusion => [nil]
+
+ # True for issues that still require attention.
+ validates :open, :inclusion => { :in => [true, false] }
+end
+
+# :nodoc: access control
+class Issue
+ def can_edit?(user)
+ repository.can_edit?(user) || (user && user.profile == author)
+ end
+end
+
+# :nodoc: activity feed integration
+class Issue
+ # Profiles following this issue.
+ has_many :subscribers, :through => :subscriber_feed_subscriptions,
+ :source => :profile
+
+ # Relation backing "subscribers".
+ #
+ # NOTE: The :dependent => :destroy option removes the FeedSubscriptions
+ # connecting subscribers, not the actual subscribers
+ has_many :subscriber_feed_subscriptions, :class_name => 'FeedSubscription',
+ :as => :topic, :inverse_of => :topic, :dependent => :destroy
+
+ # Events connected to this issue.
+ has_many :feed_items, :through => :feed_item_topic
+
+ # Relation backing "feed_items".
+ #
+ # NOTE: The :dependent => :destroy option doesn't remove the FeedItem records,
+ # it only removes the FeedItemTopic records connecting to them.
+ has_many :feed_item_topic, :as => :topic, :dependent => :destroy,
+ :inverse_of => :topic
+
+ # Updates feeds to reflect that this issue was created.
+ def publish_creation
+ # Duplicating the profile and issue title because the issue record
+ # can be deleted.
+ FeedItem.publish author, 'new_issue', self, [author, repository,
+ repository.profile, self], { :profile_name => repository.profile.name,
+ :repo_name => repository.name,
+ :author_name => author.name,
+ :issue_title => title }
+ end
+
+ # Updates feeds to reflect that this issue was destroyed.
+ def publish_deletion(author_profile)
+ FeedItem.publish author_profile, 'del_issue', self, [author_profile,
+ repository, repository.profile, self],
+ { :profile_name => repository.profile.name,
+ :repo_name => repository.name, :author_name => author.name,
+ :issue_title => title }
+ end
+end
View
4 app/models/profile.rb
@@ -11,6 +11,10 @@ class Profile < ActiveRecord::Base
has_many :profile_acl_entries, :class_name => "AclEntry", :as => :principal,
:dependent => :destroy,
:inverse_of => :principal
+
+ # The issues opened by the user behind this profile.
+ has_many :issues, :inverse_of => :author, :foreign_key => 'author_id',
+ :dependent => :destroy
# The ACL entries shown in the ACL editing UI.
def acl_entries
View
3  app/models/repository.rb
@@ -29,6 +29,9 @@ def profile_name=(new_profile_name)
# This repository's ACL. All entries have Profiles as principals.
has_many :acl_entries, :as => :subject, :dependent => :destroy,
:inverse_of => :subject
+
+ # The issues created against this repository.
+ has_many :issues, :inverse_of => :repository, :dependent => :destroy
# The repository name.
validates :name, :length => 1..64, :format => /\A\w([\w.-]*\w)?\Z/,
View
20 app/views/feed_items/_feed_item.html.erb
@@ -96,6 +96,26 @@
<%= feed_item.data[:profile_name] %>/<%= feed_item.data[:repository_name] %>
<% end %>
</div>
+
+<% when 'new_issue' %>
+ <% Rails.logger.debug "*** Feed item data: #{feed_item.data}" %>
+ created <%= link_to feed_item.data[:issue_title],
+ profile_repository_issue_path(feed_item.data[:profile_name],
+ feed_item.data[:repo_name]) %> in
+ <% if repository = feed_item.target_repository %>
+ <%= link_to_repository feed_item.target_repository %>
+ <% else %>
+ <%= feed_item.data[:profile_name] %>/<%= feed_item.data[:repository_name] %>
+ <% end %>
+ </div>
+<% when 'del_issue' %>
+ deleted <%= feed_item.data[:issue_title] %> in
+ <% if repository = feed_item.target_repository %>
+ <%= link_to_repository feed_item.target_repository %>
+ <% else %>
+ <%= feed_item.data[:profile_name] %>/<%= feed_item.data[:repository_name] %>
+ <% end %>
+ </div>
<% else %>
<% raise "Unimplemented verb #{feed_item.verb}"%>
<% end %>
View
38 app/views/issues/_closed.html.erb
@@ -0,0 +1,38 @@
+<table>
+ <tr>
+ <th>Profile</th>
+ <th>Repository</th>
+ <th>Open</th>
+ <th>Title</th>
+ <th>Description</th>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+<% Rails.logger.debug "*****Issues: #{issues}"%>
+<% issues.each do |issue| %>
+ <% if !issue.open %>
+ <tr>
+ <td><%= issue.author.name %></td>
+ <td><%= issue.repository.name %></td>
+ <td><%= issue.open %></td>
+ <td><%= issue.title %></td>
+ <td><%= issue.description %></td>
+ <td><%= link_to 'Show', profile_repository_issue_path(
+ params[:profile_name],
+ params[:repo_name], issue) %></td>
+ <% Rails.logger.debug "*****Issue: #{issue.class}"%>
+ <% if issue.can_edit? current_user %>
+ <td><%= link_to 'Edit', profile_repository_issue_path(
+ params[:profile_name],
+ params[:repo_name], issue) %></td>
+ <td><%= link_to 'Destroy', profile_repository_issue_path(
+ params[:profile_name],
+ params[:repo_name], issue),
+ confirm: 'Are you sure?',
+ method: :delete %></td>
+ <% end %>
+ </tr>
+ <% end %>
+<% end %>
+</table>
View
25 app/views/issues/_form.html.erb
@@ -0,0 +1,25 @@
+<%= form_for [@issue.repository.profile, @issue.repository, @issue] do |f| %>
+ <% if @issue.errors.any? %>
+ <div id="error_explanation">
+ <h2><%= pluralize(@issue.errors.count, "error") %> prohibited this issue from being saved:</h2>
+
+ <ul>
+ <% @issue.errors.full_messages.each do |msg| %>
+ <li><%= msg %></li>
+ <% end %>
+ </ul>
+ </div>
+ <% end %>
+
+ <div class="field">
+ <%= f.label :title %><br />
+ <%= f.text_field :title %>
+ </div>
+ <div class="field">
+ <%= f.label :description %><br />
+ <%= f.text_area :description %>
+ </div>
+ <div class="actions">
+ <%= f.submit %>
+ </div>
+<% end %>
View
39 app/views/issues/_open.html.erb
@@ -0,0 +1,39 @@
+<table>
+ <tr>
+ <th>Profile</th>
+ <th>Repository</th>
+ <th>Open</th>
+ <th>Title</th>
+ <th>Description</th>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+<% Rails.logger.debug "*****Issues: #{issues}"%>
+<% issues.each do |issue| %>
+ <% if issue.open %>
+ <tr>
+ <td><%= issue.author.name %></td>
+ <td><%= issue.repository.name %></td>
+ <td><%= issue.open %></td>
+ <td><%= issue.title %></td>
+ <td><%= issue.description %></td>
+ <td><%= link_to 'Show', profile_repository_issue_path(
+ params[:profile_name],
+ params[:repo_name], issue) %></td>
+ <% Rails.logger.debug "*****Issue Class: #{issue.class}"%>
+ <% Rails.logger.debug "*****Issue Nil: #{issue.nil?}"%>
+ <% if issue.can_edit? current_user %>
+ <td><%= link_to 'Edit', profile_repository_issue_path(
+ params[:profile_name],
+ params[:repo_name], issue) %></td>
+ <td><%= link_to 'Destroy', profile_repository_issue_path(
+ params[:profile_name],
+ params[:repo_name], issue),
+ confirm: 'Are you sure?',
+ method: :delete %></td>
+ <% end %>
+ </tr>
+ <% end %>
+<% end %>
+</table>
View
8 app/views/issues/edit.html.erb
@@ -0,0 +1,8 @@
+<h1>Editing issue</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Show', profile_repository_issue_path(@issue.repository.profile,
+ @issue.repository, @issue) %> |
+<%= link_to 'Back', profile_repository_issues_path(@issue.repository.profile,
+ @issue.repository) %>
View
11 app/views/issues/index.html.erb
@@ -0,0 +1,11 @@
+<h1>Listing issues</h1>
+
+<h2>Open Issues</h2>
+<%= render 'open', :issues => @issues %>
+
+<h2>Closed Issues</h2>
+<%= render 'closed', :issues => @issues %>
+
+<br />
+
+<%= link_to 'New Issue', new_issue_path %>
View
5 app/views/issues/new.html.erb
@@ -0,0 +1,5 @@
+<h1>New issue</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Back', profile_repository_issues_path(@profile, @repository) %>
View
32 app/views/issues/show.html.erb
@@ -0,0 +1,32 @@
+<p id="notice"><%= notice %></p>
+
+<p>
+ <b>Author:</b>
+ <%= @issue.author.name %>
+</p>
+
+<p>
+ <b>Repository:</b>
+ <%= @issue.repository.name %>
+</p>
+
+<p>
+ <b>Open:</b>
+ <%= @issue.open %>
+</p>
+
+<p>
+ <b>Title:</b>
+ <%= @issue.title %>
+</p>
+
+<p>
+ <b>Description:</b>
+ <%= @issue.description %>
+</p>
+
+
+<%= link_to 'Edit', edit_profile_repository_issue_path(
+ @issue.repository.profile, @issue.repository, @issue) %> |
+<%= link_to 'Back', profile_repository_issues_path(@issue.repository.profile,
+ @issue.repository) %>
View
2  app/views/layouts/config_vars.html.erb
@@ -2,6 +2,8 @@
<html>
<head>
<title><%= config_vars_app_name %> Vars</title>
+ <%= csrf_meta_tag %>
+ <%= favicon_link_tag %>
<%= javascript_include_tag 'application' %>
</head>
<body>
View
4 app/views/repositories/_repository.html.erb
@@ -82,6 +82,10 @@
<%= link_to 'Feed', feed_profile_repository_path(repository.profile,
repository) %>
</li>
+ <li>
+ <%= link_to 'Issues', profile_repository_issues_path(repository.profile,
+ repository) %>
+ </li>
<% if repository.can_edit? current_user %>
<li>
<%= link_to 'Sharing',
View
1  config/initializers/config_vars.rb
@@ -14,3 +14,4 @@
ConfigVars.string 'git_user', 'git'
ConfigVars.string('ssh_host') { Socket.gethostname }
ConfigVars.string('admin_email') { 'admin@' + Socket.gethostname }
+ConfigVars.string 'markdpwn', 'enabled'
View
16 config/routes.rb
@@ -1,4 +1,5 @@
Gitty::Application.routes.draw do
+
scope '_' do
authpwn_session
config_vars
@@ -109,7 +110,20 @@
get '*path' => 'blobs#raw', :as => :raw_profile_repository_blob,
:format => false
end
-
+
+ # Issues
+ resources :issues, :only => [:create, :new]
+ get 'issues' => 'issues#index', :as => :profile_repository_issues
+ #get 'issues/new' => 'issues#new', :as => :new_profile_repository_issue
+ #new_profile_repository_issue_path(
+ #params[:profile_name],
+ #params[:repo_name]), :action => 'new' %>
+ get 'issues/:id' => 'issues#show', :as => :profile_repository_issue
+ get 'issues/:id/edit(.:format)' => 'issues#edit',
+ :as => :edit_profile_repository_issue
+ put 'issues/:id' => 'issues#update'
+ delete 'issues/:id' => 'issues#destroy'
+
# Admin.
get 'edit' => 'repositories#edit', :as => :edit_profile_repository
View
16 db/migrate/20120304034951_create_issues.rb
@@ -0,0 +1,16 @@
+class CreateIssues < ActiveRecord::Migration
+ def change
+ create_table :issues do |t|
+ t.references :repository, :null => false
+ t.references :author, :null => false
+ t.boolean :open, :default => true, :null => false
+ t.string :title, :length => 160, :null => false
+ t.text :description, :length => 1.kilobyte, :null => false
+
+ t.timestamps
+ end
+
+ add_index :issues, [:author_id, :open], :unique => false, :null => false
+ add_index :issues, [:repository_id, :open], :unique => false, :null => false
+ end
+end
View
15 db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20101212042214) do
+ActiveRecord::Schema.define(:version => 20120304034951) do
create_table "acl_entries", :force => true do |t|
t.string "role", :null => false
@@ -138,6 +138,19 @@
add_index "feed_subscriptions", ["profile_id", "topic_id", "topic_type"], :name => "index_feed_subscriptions_on_profile_topic", :unique => true
add_index "feed_subscriptions", ["topic_id", "topic_type", "profile_id"], :name => "index_feed_subscriptions_on_topic_profile", :unique => true
+ create_table "issues", :force => true do |t|
+ t.integer "author_id", :null => false
+ t.integer "repository_id", :null => false
+ t.boolean "open", :default => true, :null => false
+ t.string "title", :null => false
+ t.text "description", :null => false
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
+ add_index "issues", ["author_id", "open"], :name => "index_issues_on_author_id_and_open"
+ add_index "issues", ["repository_id", "open"], :name => "index_issues_on_repository_id_and_open"
+
create_table "profiles", :force => true do |t|
t.string "name", :limit => 32, :null => false
t.string "display_name", :limit => 128, :null => false
View
20 script/git_user/setup
@@ -3,6 +3,7 @@
require 'etc'
require 'fileutils'
+require 'pathname'
# Parameter processing.
@@ -108,3 +109,22 @@ FileUtils.chmod 04750, install_keys
if `which restorecon 2>&1`[0] == ?/
Kernel.system "restorecon -R #{git_home}"
end
+
+# Fedora makes homedirs 700, so the git user can't read the app directory.
+Pathname.new(File.dirname(__FILE__)).descend do |dir|
+ dir_stat = dir.stat
+ next if dir_stat.mode & 0005 == 0005 # o+rx
+ if dir_stat.mode & 0050 == 0050 && dir_stat.gid == web_group_id
+ next # g+rx and group matches
+ end
+
+ # git can't read this directory, so we must change its permissions.
+ if dir_stat.gid == web_group_id
+ # The directory's group matches, so fix group permissions
+ dir.chmod dir.stat.mode | 0050
+ next
+ end
+
+ # Last resort: fix "other" permissions
+ dir.chmod dir.stat.mode | 0005
+end
View
6 test/fixtures/issues.yml
@@ -0,0 +1,6 @@
+costan_ghost_translated:
+ author: dexter
+ repository: costan_ghost
+ open: true
+ title: Missing translation
+ description: The text files in this project are English-only. It would be nice if they had translations.
View
66 test/functional/issues_controller_test.rb
@@ -0,0 +1,66 @@
+require 'test_helper'
+
+class IssuesControllerTest < ActionController::TestCase
+ setup do
+ @issue = issues(:costan_ghost_translated)
+ @author = users(:jane)
+
+ set_session_current_user @author
+ end
+
+ test "should get index" do
+ get :index, :profile_name => @issue.repository.profile,
+ :repo_name => @issue.repository
+ assert_response :success
+ assert_not_nil assigns(:issues)
+ end
+
+ test "should get new" do
+ get :new, :profile_name => @issue.repository.profile,
+ :repo_name => @issue.repository
+ assert_response :success
+ end
+
+ test "should create issue" do
+ assert_difference('Issue.count') do
+ post :create, :profile_name => @issue.repository.profile,
+ :repo_name => @issue.repository, :issue => @issue.attributes
+ end
+
+ assert_redirected_to profile_repository_issues_path(
+ assigns(:issue).repository.profile, assigns(:issue).repository)
+ end
+
+ test "should show issue" do
+ get :show, :profile_name => @issue.repository.profile,
+ :repo_name => @issue.repository, :id => @issue
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get :edit, :profile_name => @issue.repository.profile,
+ :repo_name => @issue.repository, :id => @issue
+ assert_response :success
+ end
+
+ test "should update issue" do
+ put :update, :profile_name => @issue.repository.profile,
+ :repo_name => @issue.repository, :id => @issue,
+ :issue => @issue.attributes
+ assert_redirected_to profile_repository_issues_path(
+ assigns(:issue).repository.profile, assigns(:issue).repository)
+ end
+
+ test "should destroy issue" do
+ assert_difference('Issue.count', -1) do
+ delete :destroy, :profile_name => @issue.repository.profile,
+ :repo_name => @issue.repository, :id => @issue
+ end
+
+ assert_redirected_to issues_path
+ end
+
+ # TODO(christy13): tests for no logged-in user
+
+ # TODO(christy13): routing tests
+end
View
8 test/integration/git_push_test.rb
@@ -78,7 +78,7 @@ def teardown
test "initial repository push and delete" do
Dir.chdir @temp_dir do
- assert Kernel.system('git init'), 'Failed to initialize repository'
+ assert Kernel.system('git init -q'), 'Failed to initialize repository'
assert Kernel.system("git remote add origin #{@win_repository.ssh_uri}"),
'Failed to add remote'
add_commit_push
@@ -95,7 +95,7 @@ def teardown
Dir.chdir @temp_dir do
- assert Kernel.system("git clone #{@win_repository.ssh_uri}"),
+ assert Kernel.system("git clone -q #{@win_repository.ssh_uri}"),
'Failed to clone repository'
FileUtils.cp 'git-ssh.sh', 'rwin'
Dir.chdir 'rwin' do
@@ -116,11 +116,11 @@ def teardown
def add_commit_push
assert Kernel.system('git add .'), 'Failed to add initial content'
- assert Kernel.system('git commit -a -m "Integration test commit"'),
+ assert Kernel.system('git commit -a -q -m "Integration test commit"'),
'Failed to make test commit'
assert Kernel.system('git tag -m "Integration test tag" integration'),
'Failed to make test tag'
- assert Kernel.system('git push --tags origin master'),
+ assert Kernel.system('git push -q --tags origin master'),
'Git push failed'
end
end
View
11 test/unit/helpers/blobs_helper_test.rb
@@ -34,6 +34,17 @@ class BlobsHelperTest < ActionView::TestCase
html = marked_up_blob @blob, '/d1/d2/a'
assert html.html_safe?, 'output not marked as html_safe'
assert_match /<div class="markdpwn-parsed-code">/, html
+ assert_no_match /<div class="markdpwn-off-code">/, html
+ assert_match "Version 1", html
+ end
+
+ test 'marked_up_blob with markdpwn=disabled' do
+ mock_repository_path @blob.repository
+ ConfigVar['markdpwn'] = 'disabled'
+ html = marked_up_blob @blob, '/d1/d2/a'
+ assert html.html_safe?, 'output not marked as html_safe'
+ assert_match /<div class="markdpwn-off-code">/, html
+ assert_no_match /<div class="markdpwn-parsed-code">/, html
assert_match "Version 1", html
end
end
View
4 test/unit/helpers/comments_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class CommentsHelperTest < ActionView::TestCase
+end
View
4 test/unit/helpers/issues_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class IssuesHelperTest < ActionView::TestCase
+end
View
72 test/unit/issue_test.rb
@@ -0,0 +1,72 @@
+require 'test_helper'
+
+class IssueTest < ActiveSupport::TestCase
+ setup do
+ @repo = repositories(:costan_ghost)
+ @issue = Issue.new :repository => @repo, :author => profiles(:dexter),
+ :open => true, :title => 'Crashes on OSX',
+ :description => 'Running Lion 10.7'
+ end
+
+ test 'setup' do
+ assert @issue.valid?
+ end
+
+ test 'requires repository' do
+ @issue.repository = nil
+ assert !@issue.valid?
+ end
+
+ test 'requires author' do
+ @issue.author = nil
+ assert !@issue.valid?
+ end
+
+ test 'requires title' do
+ @issue.title = nil
+ assert !@issue.valid?
+ end
+
+ test 'requires non-empty title' do
+ @issue.title = ''
+ assert !@issue.valid?
+ end
+
+ test 'requires description' do
+ @issue.description = nil
+ assert !@issue.valid?
+ end
+
+ test 'accepts empty description' do
+ @issue.description = ''
+ assert @issue.valid?
+ end
+
+ test 'requires open' do
+ @issue.open = nil
+ assert !@issue.valid?
+ end
+
+ test 'accepts open=false' do
+ @issue.open = false
+ assert @issue.valid?
+ end
+
+ test 'users can edit their own issues' do
+ assert @issue.can_edit?(users(:jane))
+ end
+
+ test "users can edit their repositories' issues" do
+ assert @issue.can_edit?(users(:john))
+ end
+
+ test "users can't edit random issues" do
+ assert !@issue.can_edit?(users(:rms))
+ end
+
+ test "non logged-in users can't edit issues" do
+ assert !@issue.can_edit?(nil)
+ end
+
+ # TODO(christy13): publishing tests
+end
Something went wrong with that request. Please try again.