Commit 395f3a1d authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'feature/internal_ids' of /home/git/repositories/gitlab/gitlabhq

parents 4873034a e9f1c39e
......@@ -44,7 +44,7 @@ GitLab.GfmAutoComplete =
tpl: @Issues.template
callbacks:
before_save: (issues) ->
$.map issues, (i) -> id: i.id, title: sanitize(i.title), search: "#{i.id} #{i.title}"
$.map issues, (i) -> id: i.iid, title: sanitize(i.title), search: "#{i.iid} #{i.title}"
input.one "focus", =>
$.getJSON(@dataSource).done (data) ->
......
......@@ -91,7 +91,7 @@ class Projects::IssuesController < Projects::ApplicationController
protected
def issue
@issue ||= @project.issues.find(params[:id])
@issue ||= @project.issues.find_by_iid!(params[:id])
end
def authorize_modify_issue!
......
......@@ -132,7 +132,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def merge_request
@merge_request ||= @project.merge_requests.find(params[:id])
@merge_request ||= @project.merge_requests.find_by_iid!(params[:id])
end
def authorize_modify_merge_request!
......
......@@ -104,7 +104,7 @@ class ProjectsController < Projects::ApplicationController
def autocomplete_sources
@suggestions = {
emojis: Emoji.names,
issues: @project.issues.select([:id, :title, :description]),
issues: @project.issues.select([:iid, :title, :description]),
members: @project.team.members.sort_by(&:username).map { |user| { username: user.username, name: user.name } }
}
......
......@@ -109,7 +109,7 @@ module EventsHelper
else
link_to event_note_target_path(event) do
content_tag :strong do
"#{event.note_target_type} ##{truncate event.note_target_id}"
"#{event.note_target_type} ##{truncate event.note_target_iid}"
end
end
end
......
......@@ -37,23 +37,23 @@ module IssuesHelper
end
end
def url_for_issue(issue_id)
def url_for_issue(issue_iid)
return "" if @project.nil?
if @project.used_default_issues_tracker?
url = project_issue_url project_id: @project, id: issue_id
url = project_issue_url project_id: @project, id: issue_iid
else
url = Gitlab.config.issues_tracker[@project.issues_tracker]["issues_url"]
url.gsub(':id', issue_id.to_s)
url.gsub(':id', issue_iid.to_s)
.gsub(':project_id', @project.id.to_s)
.gsub(':issues_tracker_id', @project.issues_tracker_id.to_s)
end
end
def title_for_issue(issue_id)
def title_for_issue(issue_iid)
return "" if @project.nil?
if @project.used_default_issues_tracker? && issue = @project.issues.where(id: issue_id).first
if @project.used_default_issues_tracker? && issue = @project.issues.where(iid: issue_iid).first
issue.title
else
""
......
......@@ -16,6 +16,8 @@ module Issuable
validates :author, presence: true
validates :title, presence: true, length: { within: 0..255 }
validate :set_iid, on: :create
validates :iid, presence: true, numericality: true
scope :authored, ->(user) { where(author_id: user) }
scope :assigned_to, ->(u) { where(assignee_id: u.id)}
......@@ -24,6 +26,7 @@ module Issuable
scope :unassigned, -> { where("assignee_id IS NULL") }
scope :of_projects, ->(ids) { where(project_id: ids) }
delegate :name,
:email,
to: :author,
......@@ -44,6 +47,15 @@ module Issuable
end
end
def set_iid
max_iid = project.send(self.class.name.tableize).maximum(:iid)
self.iid = max_iid.to_i + 1
end
def to_param
iid.to_s
end
def today?
Date.today == created_at.to_date
end
......
......@@ -256,6 +256,10 @@ class Event < ActiveRecord::Base
target.commit_id
end
def target_iid
target.respond_to?(:iid) ? target.iid : target_id
end
def note_short_commit_id
note_commit_id[0..8]
end
......@@ -280,6 +284,14 @@ class Event < ActiveRecord::Base
end
end
def note_target_iid
if note_target.respond_to?(:iid)
note_target.iid
else
note_target_id
end.to_s
end
def wall_note?
target.noteable_type.blank?
end
......
......@@ -250,6 +250,10 @@ class MergeRequest < ActiveRecord::Base
(source_project.root_ref? source_branch) || for_fork?
end
def project
target_project
end
private
def dump_commits(commits)
......
......@@ -197,7 +197,7 @@ class Project < ActiveRecord::Base
def issue_exists?(issue_id)
if used_default_issues_tracker?
self.issues.where(id: issue_id).first.present?
self.issues.where(iid: issue_id).first.present?
else
true
end
......
......@@ -2,7 +2,7 @@
%span.author_name= link_to_author event
%span.event_label{class: event.action_name}= event_action_name(event)
- if event.target
%strong= link_to "##{event.target_id}", [event.project, event.target]
%strong= link_to "##{event.target_iid}", [event.project, event.target]
- else
%strong= gfm event.target_title
at
......
......@@ -4,7 +4,7 @@
= check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue)
.issue-title
%span.light= "##{issue.id}"
%span.light= "##{issue.iid}"
= link_to_gfm truncate(issue.title, length: 100), project_issue_path(issue.project, issue), class: "row_title"
.issue-info
......
%h3.page-title
Issue ##{@issue.id}
Issue ##{@issue.iid}
%small
created at
......
%li{ class: mr_css_classes(merge_request) }
.merge-request-title
%span.light= "##{merge_request.id}"
%span.light= "##{merge_request.iid}"
= link_to_gfm truncate(merge_request.title, length: 80), project_merge_request_path(merge_request.target_project, merge_request), class: "row_title"
- if merge_request.merged?
%small.pull-right
......
%h3.page-title
= "Merge Request ##{@merge_request.id}:"
= "Merge Request ##{@merge_request.iid}:"
&nbsp;
-if @merge_request.for_fork?
%span.label-branch
......
......@@ -23,7 +23,7 @@
%li
merge request:
= link_to [merge_request.target_project, merge_request] do
%span ##{merge_request.id}
%span ##{merge_request.iid}
%strong.term
= truncate merge_request.title, length: 50
- if merge_request.for_fork?
......@@ -37,7 +37,7 @@
%li
issue:
= link_to [issue.project, issue] do
%span ##{issue.id}
%span ##{issue.iid}
%strong.term
= truncate issue.title, length: 50
%span.light (#{issue.project.name_with_namespace})
......
......@@ -281,7 +281,7 @@ Gitlab::Application.routes.draw do
end
end
resources :issues, except: [:destroy] do
resources :issues, constraints: {id: /\d+/}, except: [:destroy] do
collection do
post :bulk_update
end
......
class AddInternalIdsToIssuesAndMr < ActiveRecord::Migration
def change
add_column :issues, :iid, :integer
add_column :merge_requests, :iid, :integer
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130812143708) do
ActiveRecord::Schema.define(:version => 20130819182730) do
create_table "deploy_keys_projects", :force => true do |t|
t.integer "deploy_key_id", :null => false
......@@ -62,6 +62,7 @@ ActiveRecord::Schema.define(:version => 20130812143708) do
t.text "description"
t.integer "milestone_id"
t.string "state"
t.integer "iid"
end
add_index "issues", ["assignee_id"], :name => "index_issues_on_assignee_id"
......@@ -98,6 +99,7 @@ ActiveRecord::Schema.define(:version => 20130812143708) do
t.string "state"
t.string "merge_status"
t.integer "target_project_id", :null => false
t.integer "iid"
end
add_index "merge_requests", ["assignee_id"], :name => "index_merge_requests_on_assignee_id"
......
......@@ -181,7 +181,7 @@ module Gitlab
end
def reference_merge_request(identifier)
if merge_request = @project.merge_requests.where(id: identifier).first
if merge_request = @project.merge_requests.where(iid: identifier).first
link_to("!#{identifier}", project_merge_request_url(@project, merge_request), html_options.merge(title: "Merge Request: #{merge_request.title}", class: "gfm gfm-merge_request #{html_options[:class]}"))
end
end
......
desc "GITLAB | Build internal ids for issues and merge requests"
task migrate_iids: :environment do
puts 'Issues'.yellow
Issue.where(iid: nil).find_each(batch_size: 100) do |issue|
begin
issue.set_iid
if issue.update_attribute(:iid, mr.iid)
print '.'
else
print 'F'
end
rescue
print 'F'
end
end
puts 'done'
puts 'Merge Requests'.yellow
MergeRequest.where(iid: nil).find_each(batch_size: 100) do |mr|
begin
mr.set_iid
if mr.update_attribute(:iid, mr.iid)
print '.'
else
print 'F'
end
rescue => ex
print 'F'
end
end
puts 'done'
end
......@@ -8,13 +8,13 @@ describe Projects::MergeRequestsController do
before do
sign_in(user)
project.team << [user, :master]
Projects::MergeRequestsController.any_instance.stub(validates_merge_request: true)
Projects::MergeRequestsController.any_instance.stub(validates_merge_request: true, )
end
describe "#show" do
shared_examples "export merge as" do |format|
it "should generally work" do
get :show, project_id: project.code, id: merge_request.id, format: format
get :show, project_id: project.code, id: merge_request.iid, format: format
expect(response).to be_success
end
......@@ -22,11 +22,11 @@ describe Projects::MergeRequestsController do
it "should generate it" do
MergeRequest.any_instance.should_receive(:"to_#{format}")
get :show, project_id: project.code, id: merge_request.id, format: format
get :show, project_id: project.code, id: merge_request.iid, format: format
end
it "should render it" do
get :show, project_id: project.code, id: merge_request.id, format: format
get :show, project_id: project.code, id: merge_request.iid, format: format
expect(response.body).to eq((merge_request.send(:"to_#{format}",user)).to_s)
end
......@@ -34,7 +34,7 @@ describe Projects::MergeRequestsController do
it "should not escape Html" do
MergeRequest.any_instance.stub(:"to_#{format}").and_return('HTML entities &<>" ')
get :show, project_id: project.code, id: merge_request.id, format: format
get :show, project_id: project.code, id: merge_request.iid, format: format
expect(response.body).to_not include('&amp;')
expect(response.body).to_not include('&gt;')
......@@ -48,7 +48,7 @@ describe Projects::MergeRequestsController do
let(:format) { :diff }
it "should really only be a git diff" do
get :show, project_id: project.code, id: merge_request.id, format: format
get :show, project_id: project.code, id: merge_request.iid, format: format
expect(response.body).to start_with("diff --git")
end
......@@ -59,24 +59,13 @@ describe Projects::MergeRequestsController do
let(:format) { :patch }
it "should really be a git email patch with commit" do
get :show, project_id: project.code, id: merge_request.id, format: format
get :show, project_id: project.code, id: merge_request.iid, format: format
expect(response.body[0..100]).to start_with("From #{merge_request.commits.last.id}")
end
# TODO: fix or remove
#it "should contain as many patches as there are commits" do
#get :show, project_id: project.code, id: merge_request.id, format: format
#patch_count = merge_request.commits.count
#merge_request.commits.each_with_index do |commit, patch_num|
#expect(response.body).to match(/^From #{commit.id}/)
#expect(response.body).to match(/^Subject: \[PATCH #{patch_num}\/#{patch_count}\]/)
#end
#end
it "should contain git diffs" do
get :show, project_id: project.code, id: merge_request.id, format: format
get :show, project_id: project.code, id: merge_request.iid, format: format
expect(response.body).to match(/^diff --git/)
end
......
......@@ -11,7 +11,7 @@ describe "GitLab Flavored Markdown" do
end
before do
Commit.any_instance.stub(title: "fix ##{issue.id}\n\nask @#{fred.username} for details")
Commit.any_instance.stub(title: "fix ##{issue.iid}\n\nask @#{fred.username} for details")
end
let(:commit) { project.repository.commit }
......@@ -25,13 +25,13 @@ describe "GitLab Flavored Markdown" do
it "should render title in commits#index" do
visit project_commits_path(project, 'master', limit: 1)
page.should have_link("##{issue.id}")
page.should have_link("##{issue.iid}")
end
it "should render title in commits#show" do
visit project_commit_path(project, commit)
page.should have_link("##{issue.id}")
page.should have_link("##{issue.iid}")
end
it "should render description in commits#show" do
......@@ -43,7 +43,7 @@ describe "GitLab Flavored Markdown" do
it "should render title in repositories#branches" do
visit project_branches_path(project)
page.should have_link("##{issue.id}")
page.should have_link("##{issue.iid}")
end
end
......@@ -57,20 +57,20 @@ describe "GitLab Flavored Markdown" do
author: @user,
assignee: @user,
project: project,
title: "fix ##{@other_issue.id}",
title: "fix ##{@other_issue.iid}",
description: "ask @#{fred.username} for details")
end
it "should render subject in issues#index" do
visit project_issues_path(project)
page.should have_link("##{@other_issue.id}")
page.should have_link("##{@other_issue.iid}")
end
it "should render subject in issues#show" do
visit project_issue_path(project, @issue)
page.should have_link("##{@other_issue.id}")
page.should have_link("##{@other_issue.iid}")
end
it "should render details in issues#show" do
......@@ -83,19 +83,19 @@ describe "GitLab Flavored Markdown" do
describe "for merge requests" do
before do
@merge_request = create(:merge_request, source_project: project, target_project: project, title: "fix ##{issue.id}")
@merge_request = create(:merge_request, source_project: project, target_project: project, title: "fix ##{issue.iid}")
end
it "should render title in merge_requests#index" do
visit project_merge_requests_path(project)
page.should have_link("##{issue.id}")
page.should have_link("##{issue.iid}")
end
it "should render title in merge_requests#show" do
visit project_merge_request_path(project, @merge_request)
page.should have_link("##{issue.id}")
page.should have_link("##{issue.iid}")
end
end
......@@ -104,20 +104,20 @@ describe "GitLab Flavored Markdown" do
before do
@milestone = create(:milestone,
project: project,
title: "fix ##{issue.id}",
title: "fix ##{issue.iid}",
description: "ask @#{fred.username} for details")
end
it "should render title in milestones#index" do
visit project_milestones_path(project)
page.should have_link("##{issue.id}")
page.should have_link("##{issue.iid}")
end
it "should render title in milestones#show" do
visit project_milestone_path(project, @milestone)
page.should have_link("##{issue.id}")
page.should have_link("##{issue.iid}")
end
it "should render description in milestones#show" do
......
......@@ -20,7 +20,7 @@ describe GitlabMarkdownHelper do
describe "#gfm" do
it "should return unaltered text if project is nil" do
actual = "Testing references: ##{issue.id}"
actual = "Testing references: ##{issue.iid}"
gfm(actual).should_not == actual
......@@ -175,14 +175,14 @@ describe GitlabMarkdownHelper do
describe "referencing an issue" do
let(:object) { issue }
let(:reference) { "##{issue.id}" }
let(:reference) { "##{issue.iid}" }
include_examples 'referenced object'
end
describe "referencing a merge request" do
let(:object) { merge_request }
let(:reference) { "!#{merge_request.id}" }
let(:reference) { "!#{merge_request.iid}" }
include_examples 'referenced object'
end
......@@ -230,7 +230,7 @@ describe GitlabMarkdownHelper do
end
describe "referencing multiple objects" do
let(:actual) { "!#{merge_request.id} -> #{commit.id} -> ##{issue.id}" }
let(:actual) { "!#{merge_request.iid} -> #{commit.id} -> ##{issue.iid}" }
it "should link to the merge request" do
expected = project_merge_request_path(project, merge_request)
......@@ -299,7 +299,7 @@ describe GitlabMarkdownHelper do
let(:issues) { create_list(:issue, 2, project: project) }
it "should handle references nested in links with all the text" do
actual = link_to_gfm("This should finally fix ##{issues[0].id} and ##{issues[1].id} for real", commit_path)
actual = link_to_gfm("This should finally fix ##{issues[0].iid} and ##{issues[1].iid} for real", commit_path)
# Break the result into groups of links with their content, without
# closing tags
......@@ -311,7 +311,7 @@ describe GitlabMarkdownHelper do
# First issue link
groups[1].should match(/href="#{project_issue_url(project, issues[0])}"/)
groups[1].should match(/##{issues[0].id}$/)
groups[1].should match(/##{issues[0].iid}$/)
# Internal commit link
groups[2].should match(/href="#{commit_path}"/)
......@@ -319,7 +319,7 @@ describe GitlabMarkdownHelper do
# Second issue link
groups[3].should match(/href="#{project_issue_url(project, issues[1])}"/)
groups[3].should match(/##{issues[1].id}$/)
groups[3].should match(/##{issues[1].iid}$/)
# Trailing commit link
groups[4].should match(/href="#{commit_path}"/)
......@@ -332,7 +332,7 @@ describe GitlabMarkdownHelper do
end
it "escapes HTML passed in as the body" do
actual = "This is a <h1>test</h1> - see ##{issues[0].id}"
actual = "This is a <h1>test</h1> - see ##{issues[0].iid}"
link_to_gfm(actual, commit_path).should match('&lt;h1&gt;test&lt;/h1&gt;')
end
end
......@@ -345,25 +345,25 @@ describe GitlabMarkdownHelper do
end
it "should handle references in headers" do
actual = "\n# Working around ##{issue.id}\n## Apply !#{merge_request.id}"
actual = "\n# Working around ##{issue.iid}\n## Apply !#{merge_request.iid}"
markdown(actual).should match(%r{<h1[^<]*>Working around <a.+>##{issue.id}</a></h1>})
markdown(actual).should match(%r{<h2[^<]*>Apply <a.+>!#{merge_request.id}</a></h2>})
markdown(actual).should match(%r{<h1[^<]*>Working around <a.+>##{issue.iid}</a></h1>})
markdown(actual).should match(%r{<h2[^<]*>Apply <a.+>!#{merge_request.iid}</a></h2>})
end
it "should handle references in lists" do
project.team << [user, :master]
actual = "\n* dark: ##{issue.id}\n* light by @#{member.user.username}"
actual = "\n* dark: ##{issue.iid}\n* light by @#{member.user.username}"
markdown(actual).should match(%r{<li>dark: <a.+>##{issue.id}</a></li>})
markdown(actual).should match(%r{<li>dark: <a.+>##{issue.iid}</a></li>})
markdown(actual).should match(%r{<li>light by <a.+>@#{member.user.username}</a></li>})
end
it "should handle references in <em>" do
actual = "Apply _!#{merge_request.id}_ ASAP"
actual = "Apply _!#{merge_request.iid}_ ASAP"
markdown(actual).should match(%r{Apply <em><a.+>!#{merge_request.id}</a></em>})
markdown(actual).should match(%r{Apply <em><a.+>!#{merge_request.iid}</a></em>})
end
it "should leave code blocks untouched" do
......@@ -379,19 +379,19 @@ describe GitlabMarkdownHelper do
end
it "should leave ref-like autolinks untouched" do
markdown("look at http://example.tld/#!#{merge_request.id}").should == "<p>look at <a href=\"http://example.tld/#!#{merge_request.id}\">http://example.tld/#!#{merge_request.id}</a></p>\n"
markdown("look at http://example.tld/#!#{merge_request.iid}").should == "<p>look at <a href=\"http://example.tld/#!#{merge_request.iid}\">http://example.tld/#!#{merge_request.iid}</a></p>\n"
end
it "should leave ref-like href of 'manual' links untouched" do
markdown("why not [inspect !#{merge_request.id}](http://example.tld/#!#{merge_request.id})").should == "<p>why not <a href=\"http://example.tld/#!#{merge_request.id}\">inspect </a><a href=\"#{project_merge_request_url(project, merge_request)}\" class=\"gfm gfm-merge_request \" title=\"Merge Request: #{merge_request.title}\">!#{merge_request.id}</a><a href=\"http://example.tld/#!#{merge_request.id}\"></a></p>\n"
markdown("why not [inspect !#{merge_request.iid}](http://example.tld/#!#{merge_request.iid})").should == "<p>why not <a href=\"http://example.tld/#!#{merge_request.iid}\">inspect </a><a href=\"#{project_merge_request_url(project, merge_request)}\" class=\"gfm gfm-merge_request \" title=\"Merge Request: #{merge_request.title}\">!#{merge_request.iid}</a><a href=\"http://example.tld/#!#{merge_request.iid}\"></a></p>\n"
end
it "should leave ref-like src of images untouched" do
markdown("screen shot: ![some image](http://example.tld/#!#{merge_request.id})").should == "<p>screen shot: <img src=\"http://example.tld/#!#{merge_request.id}\" alt=\"some image\"></p>\n"
markdown("screen shot: ![some image](http://example.tld/#!#{merge_request.iid})").should == "<p>screen shot: <img src=\"http://example.tld/#!#{merge_request.iid}\" alt=\"some image\"></p>\n"
end
it "should generate absolute urls for refs" do
markdown("##{issue.id}").should include(project_issue_url(project, issue))
markdown("##{issue.iid}").should include(project_issue_url(project, issue))
end
it "should generate absolute urls for emoji" do
......
......@@ -8,7 +8,7 @@ describe IssuesHelper do
describe :title_for_issue do
it "should return issue title if used internal tracker" do
@project = project
title_for_issue(issue.id).should eq issue.title
title_for_issue(issue.iid).should eq issue.title
end
it "should always return empty string if used external tracker" do
......@@ -61,7 +61,7 @@ describe IssuesHelper do
it "should return internal path if used internal tracker" do
@project = project
url_for_issue(issue.id).should match(int_expected)
url_for_issue(issue.iid).should match(int_expected)
end
it "should return path to external tracker" do
......@@ -73,7 +73,7 @@ describe IssuesHelper do
it "should return empty string if project nil" do
@project = nil
url_for_issue(issue.id).should eq ""
url_for_issue(issue.iid).should eq ""
end
end
......
......@@ -11,7 +11,9 @@ describe Issue, "Issuable" do
end
describe "Validation" do
before { subject.stub(set_iid: false) }
it { should validate_presence_of(:project) }
it { should validate_presence_of(:iid) }
it { should validate_presence_of(:author) }
it { should validate_presence_of(:title) }
it { should ensure_length_of(:title).is_at_least(0).is_at_most(255) }
......
......@@ -201,11 +201,11 @@ describe Project do
let(:ext_project) { create(:redmine_project) }
it "should be true or if used internal tracker and issue exists" do
project.issue_exists?(existed_issue.id).should be_true
project.issue_exists?(existed_issue.iid).should be_true
end
it "should be false or if used internal tracker and issue not exists" do
project.issue_exists?(not_existed_issue.id).should be_false
project.issue_exists?(not_existed_issue.iid).should be_false
end
it "should always be true if used other tracker" do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment