commit
ddeb1a2a0f
@ -1,122 +0,0 @@ |
||||
#-- copyright |
||||
# ChiliProject is a project management system. |
||||
# |
||||
# Copyright (C) 2010-2011 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
class GeneralizeJournals < ActiveRecord::Migration |
||||
def self.up |
||||
# This is provided here for migrating up after the JournalDetails has been removed |
||||
unless Object.const_defined?("JournalDetails") |
||||
Object.const_set("JournalDetails", Class.new(ActiveRecord::Base)) |
||||
end |
||||
|
||||
change_table :journals do |t| |
||||
t.rename :journalized_id, :journaled_id |
||||
t.rename :created_on, :created_at |
||||
|
||||
t.integer :version, :default => 0, :null => false |
||||
t.string :activity_type |
||||
t.text :changes |
||||
t.string :type |
||||
|
||||
t.index :journaled_id |
||||
t.index :activity_type |
||||
t.index :created_at |
||||
t.index :type |
||||
end |
||||
|
||||
Journal.all.group_by(&:journaled_id).each_pair do |id, journals| |
||||
journals.sort_by(&:created_at).each_with_index do |j, idx| |
||||
j.update_attribute(:type, "#{j.journalized_type}Journal") |
||||
j.update_attribute(:version, idx + 1) |
||||
# FIXME: Find some way to choose the right activity here |
||||
j.update_attribute(:activity_type, j.journalized_type.constantize.activity_provider_options.keys.first) |
||||
end |
||||
end |
||||
|
||||
change_table :journals do |t| |
||||
t.remove :journalized_type |
||||
end |
||||
|
||||
JournalDetails.all.each do |detail| |
||||
journal = Journal.find(detail.journal_id) |
||||
changes = journal.changes || {} |
||||
if detail.property == 'attr' # Standard attributes |
||||
changes[detail.prop_key.to_s] = [detail.old_value, detail.value] |
||||
elsif detail.property == 'cf' # Custom fields |
||||
changes["custom_values_" + detail.prop_key.to_s] = [detail.old_value, detail.value] |
||||
elsif detail.property == 'attachment' # Attachment |
||||
changes["attachments_" + detail.prop_key.to_s] = [detail.old_value, detail.value] |
||||
end |
||||
journal.update_attribute(:changes, changes.to_yaml) |
||||
end |
||||
|
||||
# Create creation journals for all activity providers |
||||
providers = Redmine::Activity.providers.collect {|k, v| v.collect(&:constantize) }.flatten.compact.uniq |
||||
providers.each do |p| |
||||
next unless p.table_exists? # Objects not in the DB yet need creation journal entries |
||||
p.find(:all).each do |o| |
||||
unless o.last_journal |
||||
o.send(:update_journal) |
||||
created_at = nil |
||||
[:created_at, :created_on, :updated_at, :updated_on].each do |m| |
||||
if o.respond_to? m |
||||
created_at = o.send(m) |
||||
break |
||||
end |
||||
end |
||||
p "Updating #{o}" |
||||
o.last_journal.update_attribute(:created_at, created_at) if created_at and o.last_journal |
||||
end |
||||
end |
||||
end |
||||
|
||||
# drop_table :journal_details |
||||
end |
||||
|
||||
def self.down |
||||
# create_table "journal_details", :force => true do |t| |
||||
# t.integer "journal_id", :default => 0, :null => false |
||||
# t.string "property", :limit => 30, :default => "", :null => false |
||||
# t.string "prop_key", :limit => 30, :default => "", :null => false |
||||
# t.string "old_value" |
||||
# t.string "value" |
||||
# end |
||||
|
||||
change_table "journals" do |t| |
||||
t.rename :journaled_id, :journalized_id |
||||
t.rename :created_at, :created_on |
||||
|
||||
t.string :journalized_type, :limit => 30, :default => "", :null => false |
||||
end |
||||
|
||||
custom_field_names = CustomField.all.group_by(&:type)[IssueCustomField].collect(&:name) |
||||
Journal.all.each do |j| |
||||
# Can't used j.journalized.class.name because the model changes make it nil |
||||
j.update_attribute(:journalized_type, j.type.to_s.sub("Journal","")) if j.type.present? |
||||
end |
||||
|
||||
change_table "journals" do |t| |
||||
t.remove_index :journaled_id |
||||
t.remove_index :activity_type |
||||
t.remove_index :created_at |
||||
t.remove_index :type |
||||
|
||||
t.remove :type |
||||
t.remove :version |
||||
t.remove :activity_type |
||||
t.remove :changes |
||||
end |
||||
|
||||
# add_index "journal_details", ["journal_id"], :name => "journal_details_journal_id" |
||||
# add_index "journals", ["journalized_id", "journalized_type"], :name => "journals_journalized_id" |
||||
end |
||||
end |
@ -0,0 +1,55 @@ |
||||
#-- copyright |
||||
# ChiliProject is a project management system. |
||||
# |
||||
# Copyright (C) 2010-2011 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
class PrepareJournalsForActsAsJournalized < ActiveRecord::Migration |
||||
def self.up |
||||
# This is provided here for migrating up after the JournalDetails has been removed |
||||
unless Object.const_defined?("JournalDetails") |
||||
Object.const_set("JournalDetails", Class.new(ActiveRecord::Base)) |
||||
end |
||||
|
||||
change_table :journals do |t| |
||||
t.rename :journalized_id, :journaled_id |
||||
t.rename :created_on, :created_at |
||||
|
||||
t.integer :version, :default => 0, :null => false |
||||
t.string :activity_type |
||||
t.text :changes |
||||
t.string :type |
||||
|
||||
t.index :journaled_id |
||||
t.index :activity_type |
||||
t.index :created_at |
||||
t.index :type |
||||
end |
||||
|
||||
end |
||||
|
||||
def self.down |
||||
change_table "journals" do |t| |
||||
t.rename :journaled_id, :journalized_id |
||||
t.rename :created_at, :created_on |
||||
|
||||
t.remove_index :journaled_id |
||||
t.remove_index :activity_type |
||||
t.remove_index :created_at |
||||
t.remove_index :type |
||||
|
||||
t.remove :type |
||||
t.remove :version |
||||
t.remove :activity_type |
||||
t.remove :changes |
||||
end |
||||
|
||||
end |
||||
end |
@ -0,0 +1,47 @@ |
||||
Redmine::Activity.providers.values.flatten.uniq.collect(&:underscore).each {|klass| require_dependency klass } |
||||
|
||||
class UpdateJournalsForActsAsJournalized < ActiveRecord::Migration |
||||
def self.up |
||||
# This is provided here for migrating up after the JournalDetails has been removed |
||||
unless Object.const_defined?("JournalDetails") |
||||
Object.const_set("JournalDetails", Class.new(ActiveRecord::Base)) |
||||
end |
||||
|
||||
say_with_time("Updating existing Journals...") do |
||||
Journal.all.group_by(&:journaled_id).each_pair do |id, journals| |
||||
journals.sort_by(&:created_at).each_with_index do |j, idx| |
||||
# Recast the basic Journal into it's STI journalized class so callbacks work (#467) |
||||
klass_name = "#{j.journalized_type}Journal" |
||||
j = j.becomes(klass_name.constantize) |
||||
j.type = klass_name |
||||
j.version = idx + 2 # initial journal should be 1 |
||||
j.activity_type = j.journalized_type.constantize.activity_provider_options.keys.first |
||||
begin |
||||
j.save(false) |
||||
rescue ActiveRecord::RecordInvalid => ex |
||||
puts "Error saving: #{j.class.to_s}##{j.id} - #{ex.message}" |
||||
end |
||||
|
||||
end |
||||
end |
||||
end |
||||
|
||||
change_table :journals do |t| |
||||
t.remove :journalized_type |
||||
end |
||||
end |
||||
|
||||
def self.down |
||||
change_table "journals" do |t| |
||||
t.string :journalized_type, :limit => 30, :default => "", :null => false |
||||
end |
||||
|
||||
custom_field_names = CustomField.all.group_by(&:type)[IssueCustomField].collect(&:name) |
||||
Journal.all.each do |j| |
||||
# Can't used j.journalized.class.name because the model changes make it nil |
||||
j.update_attribute(:journalized_type, j.type.to_s.sub("Journal","")) if j.type.present? |
||||
end |
||||
|
||||
end |
||||
end |
||||
|
@ -0,0 +1,80 @@ |
||||
class BuildInitialJournalsForActsAsJournalized < ActiveRecord::Migration |
||||
def self.up |
||||
# This is provided here for migrating up after the JournalDetails has been removed |
||||
unless Object.const_defined?("JournalDetails") |
||||
Object.const_set("JournalDetails", Class.new(ActiveRecord::Base)) |
||||
end |
||||
|
||||
# Reset class and subclasses, otherwise they will try to save using older attributes |
||||
Journal.reset_column_information |
||||
Journal.send(:subclasses).each do |klass| |
||||
klass.reset_column_information if klass.respond_to?(:reset_column_information) |
||||
end |
||||
|
||||
providers = Redmine::Activity.providers.collect {|k, v| v.collect(&:constantize) }.flatten.compact.uniq |
||||
providers.each do |p| |
||||
next unless p.table_exists? # Objects not in the DB yet need creation journal entries |
||||
|
||||
say_with_time("Building initial journals for #{p.class_name}") do |
||||
|
||||
activity_type = p.activity_provider_options.keys.first |
||||
|
||||
p.find(:all).each do |o| |
||||
# Create initial journals |
||||
new_journal = o.journals.build |
||||
# Mock up a list of changes for the creation journal based on Class defaults |
||||
new_attributes = o.class.new.attributes.except(o.class.primary_key, |
||||
o.class.inheritance_column, |
||||
:updated_on, |
||||
:updated_at, |
||||
:lock_version, |
||||
:lft, |
||||
:rgt) |
||||
creation_changes = {} |
||||
new_attributes.each do |name, default_value| |
||||
# Set changes based on the initial value to current. Can't get creation value without |
||||
# rebuiling the object history |
||||
creation_changes[name] = [default_value, o.send(name)] # [initial_value, creation_value] |
||||
end |
||||
new_journal.changes = creation_changes |
||||
new_journal.version = 1 |
||||
new_journal.activity_type = activity_type |
||||
|
||||
if o.respond_to?(:author) |
||||
new_journal.user = o.author |
||||
elsif o.respond_to?(:user) |
||||
new_journal.user = o.user |
||||
end |
||||
# Using rescue and save! here because either the Journal or the |
||||
# touched record could fail. This will catch either error and continue |
||||
begin |
||||
new_journal.save! |
||||
|
||||
new_journal.reload |
||||
|
||||
# Backdate journal |
||||
if o.respond_to?(:created_at) |
||||
new_journal.update_attribute(:created_at, o.created_at) |
||||
elsif o.respond_to?(:created_on) |
||||
new_journal.update_attribute(:created_at, o.created_on) |
||||
end |
||||
rescue ActiveRecord::RecordInvalid => ex |
||||
if new_journal.errors.count == 1 && new_journal.errors.first[0] == "version" |
||||
# Skip, only error was from creating the initial journal for a record that already had one. |
||||
else |
||||
puts "ERROR: errors creating the initial journal for #{o.class.to_s}##{o.id.to_s}:" |
||||
puts " #{ex.message}" |
||||
end |
||||
end |
||||
end |
||||
|
||||
end |
||||
end |
||||
|
||||
end |
||||
|
||||
def self.down |
||||
# No-op |
||||
end |
||||
|
||||
end |
@ -0,0 +1,35 @@ |
||||
class AddChangesFromJournalDetailsForActsAsJournalized < ActiveRecord::Migration |
||||
def self.up |
||||
# This is provided here for migrating up after the JournalDetails has been removed |
||||
unless Object.const_defined?("JournalDetails") |
||||
Object.const_set("JournalDetails", Class.new(ActiveRecord::Base)) |
||||
end |
||||
|
||||
say_with_time("Adding changes from JournalDetails") do |
||||
JournalDetails.all.each do |detail| |
||||
journal = Journal.find(detail.journal_id) |
||||
changes = journal.changes || {} |
||||
if detail.property == 'attr' # Standard attributes |
||||
changes[detail.prop_key.to_s] = [detail.old_value, detail.value] |
||||
elsif detail.property == 'cf' # Custom fields |
||||
changes["custom_values_" + detail.prop_key.to_s] = [detail.old_value, detail.value] |
||||
elsif detail.property == 'attachment' # Attachment |
||||
changes["attachments_" + detail.prop_key.to_s] = [detail.old_value, detail.value] |
||||
end |
||||
begin |
||||
journal.update_attribute(:changes, changes.to_yaml) |
||||
rescue ActiveRecord::RecordInvalid => ex |
||||
puts "Error saving: #{journal.class.to_s}##{journal.id} - #{ex.message}" |
||||
end |
||||
|
||||
end |
||||
|
||||
end |
||||
|
||||
end |
||||
|
||||
def self.down |
||||
# No-op |
||||
end |
||||
|
||||
end |
@ -0,0 +1,37 @@ |
||||
#-- copyright |
||||
# ChiliProject is a project management system. |
||||
# |
||||
# Copyright (C) 2010-2011 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require 'fileutils' |
||||
|
||||
desc "Package up a ChiliProject release from git. example: `rake release[1.1.0]`" |
||||
task :release, [:version] do |task, args| |
||||
version = args[:version] |
||||
abort "Missing version in the form of 1.0.0" unless version.present? |
||||
|
||||
dir = Pathname.new(ENV['HOME']) + 'dev' + 'chiliproject' + 'packages' |
||||
FileUtils.mkdir_p dir |
||||
|
||||
commands = [ |
||||
"cd #{dir}", |
||||
"git clone git://github.com/chiliproject/chiliproject.git chiliproject-#{version}", |
||||
"cd chiliproject-#{version}/", |
||||
"git checkout v#{version}", |
||||
"rm -vRf #{dir}/chiliproject-#{version}/.git", |
||||
"cd #{dir}", |
||||
"tar -zcvf chiliproject-#{version}.tar.gz chiliproject-#{version}", |
||||
"zip -r -9 chiliproject-#{version}.zip chiliproject-#{version}", |
||||
"md5sum chiliproject-#{version}.tar.gz chiliproject-#{version}.zip > chiliproject-#{version}.md5sum", |
||||
"echo 'Release ready'" |
||||
].join(' && ') |
||||
system(commands) |
||||
end |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,74 @@ |
||||
Return-Path: <jsmith@somenet.foo> |
||||
Received: from osiris ([127.0.0.1]) |
||||
by OSIRIS |
||||
with hMailServer ; Sat, 21 Jun 2008 18:41:39 +0200 |
||||
Message-ID: <006a01c8d3bd$ad9baec0$0a00a8c0@osiris> |
||||
In-Reply-To: <chiliproject.issue_journal-3.20110617112550@example.net> |
||||
From: "John Smith" <jsmith@somenet.foo> |
||||
To: <redmine@somenet.foo> |
||||
References: <485d0ad366c88_d7014663a025f@osiris.tmail> |
||||
Subject: Re: Add ingredients categories |
||||
Date: Sat, 21 Jun 2008 18:41:39 +0200 |
||||
MIME-Version: 1.0 |
||||
Content-Type: multipart/alternative; |
||||
boundary="----=_NextPart_000_0067_01C8D3CE.711F9CC0" |
||||
X-Priority: 3 |
||||
X-MSMail-Priority: Normal |
||||
X-Mailer: Microsoft Outlook Express 6.00.2900.2869 |
||||
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869 |
||||
|
||||
This is a multi-part message in MIME format. |
||||
|
||||
------=_NextPart_000_0067_01C8D3CE.711F9CC0 |
||||
Content-Type: text/plain; |
||||
charset="utf-8" |
||||
Content-Transfer-Encoding: quoted-printable |
||||
|
||||
This is reply |
||||
------=_NextPart_000_0067_01C8D3CE.711F9CC0 |
||||
Content-Type: text/html; |
||||
charset="utf-8" |
||||
Content-Transfer-Encoding: quoted-printable |
||||
|
||||
=EF=BB=BF<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
||||
<HTML><HEAD> |
||||
<META http-equiv=3DContent-Type content=3D"text/html; charset=3Dutf-8"> |
||||
<STYLE>BODY { |
||||
FONT-SIZE: 0.8em; COLOR: #484848; FONT-FAMILY: Verdana, sans-serif |
||||
} |
||||
BODY H1 { |
||||
FONT-SIZE: 1.2em; MARGIN: 0px; FONT-FAMILY: "Trebuchet MS", Verdana, = |
||||
sans-serif |
||||
} |
||||
A { |
||||
COLOR: #2a5685 |
||||
} |
||||
A:link { |
||||
COLOR: #2a5685 |
||||
} |
||||
A:visited { |
||||
COLOR: #2a5685 |
||||
} |
||||
A:hover { |
||||
COLOR: #c61a1a |
||||
} |
||||
A:active { |
||||
COLOR: #c61a1a |
||||
} |
||||
HR { |
||||
BORDER-RIGHT: 0px; BORDER-TOP: 0px; BACKGROUND: #ccc; BORDER-LEFT: 0px; = |
||||
WIDTH: 100%; BORDER-BOTTOM: 0px; HEIGHT: 1px |
||||
} |
||||
.footer { |
||||
FONT-SIZE: 0.8em; FONT-STYLE: italic |
||||
} |
||||
</STYLE> |
||||
|
||||
<META content=3D"MSHTML 6.00.2900.2883" name=3DGENERATOR></HEAD> |
||||
<BODY bgColor=3D#ffffff> |
||||
<DIV><SPAN class=3Dfooter><FONT face=3DArial color=3D#000000 = |
||||
size=3D2>This is=20 |
||||
reply</FONT></DIV></SPAN></BODY></HTML> |
||||
|
||||
------=_NextPart_000_0067_01C8D3CE.711F9CC0-- |
||||
|
Loading…
Reference in new issue