[Bps-public-commit] r16687 - in sd/branches/init-and-clone: . lib/App lib/App/SD lib/App/SD/CLI lib/App/SD/CLI/Command lib/App/SD/CLI/Command/Help lib/App/SD/CLI/Command/Ticket lib/App/SD/CLI/Model lib/App/SD/Model lib/App/SD/Replica lib/App/SD/Replica/hm t
jesse at bestpractical.com
jesse at bestpractical.com
Thu Nov 6 01:48:56 EST 2008
Author: jesse
Date: Thu Nov 6 01:48:55 2008
New Revision: 16687
Added:
sd/branches/init-and-clone/lib/App/SD/CLI/Command/Help/Config.pm
sd/branches/init-and-clone/lib/App/SD/Config.pm
sd/branches/init-and-clone/t/05-config-file-loading.t
Removed:
sd/branches/init-and-clone/lib/App/SD/CLI/Command/Server.pm
sd/branches/init-and-clone/lib/App/SD/CLI/Command/Ticket/Resolve.pm
Modified:
sd/branches/init-and-clone/ (props changed)
sd/branches/init-and-clone/lib/App/SD.pm
sd/branches/init-and-clone/lib/App/SD/CLI.pm
sd/branches/init-and-clone/lib/App/SD/CLI/Command.pm
sd/branches/init-and-clone/lib/App/SD/CLI/Command/Help.pm
sd/branches/init-and-clone/lib/App/SD/CLI/Command/Help/Environment.pm
sd/branches/init-and-clone/lib/App/SD/CLI/Command/Ticket/Update.pm
sd/branches/init-and-clone/lib/App/SD/CLI/Dispatcher.pm
sd/branches/init-and-clone/lib/App/SD/CLI/Model/Ticket.pm
sd/branches/init-and-clone/lib/App/SD/Model/Ticket.pm
sd/branches/init-and-clone/lib/App/SD/Replica/hm.pm
sd/branches/init-and-clone/lib/App/SD/Replica/hm/PushEncoder.pm
sd/branches/init-and-clone/lib/App/SD/Replica/rt/PullEncoder.pm
sd/branches/init-and-clone/lib/App/SD/Test.pm
sd/branches/init-and-clone/t/01-create.t
sd/branches/init-and-clone/t/02-create-with-editor.t
sd/branches/init-and-clone/t/03-update-ticket-with-editor.t
sd/branches/init-and-clone/t/sd-comments.t
sd/branches/init-and-clone/t/sd-hm-comments.t
sd/branches/init-and-clone/t/sd-hm-comments1.t
sd/branches/init-and-clone/t/sd-hm-group.t
sd/branches/init-and-clone/t/sd-hm-tag.t
sd/branches/init-and-clone/t/sd-hm.t
sd/branches/init-and-clone/t/sd-rt-hm-single.t
sd/branches/init-and-clone/t/sd-rt-permission.t
sd/branches/init-and-clone/t/sd-rt.t
Log:
r49325 at 31b: jesse | 2008-11-06 10:20:09 +0900
Mergedown and local changes for the clone/init branch
Modified: sd/branches/init-and-clone/lib/App/SD.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD.pm Thu Nov 6 01:48:55 2008
@@ -1,9 +1,16 @@
package App::SD;
use Moose;
+use App::SD::Config;
extends 'Prophet::App';
our $VERSION = '0.01';
+has +config => (
+ default => sub {
+ my $self = shift;
+ return App::SD::Config->new(app_handle => $self);
+ }
+);
sub database_settings {
{
Modified: sd/branches/init-and-clone/lib/App/SD/CLI.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD/CLI.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD/CLI.pm Thu Nov 6 01:48:55 2008
@@ -10,7 +10,7 @@
default => 'App::SD',
);
-sub dispatcher { "App::SD::CLI::Dispatcher" }
+sub dispatcher_class { "App::SD::CLI::Dispatcher" }
__PACKAGE__->meta->make_immutable;
no Moose;
Modified: sd/branches/init-and-clone/lib/App/SD/CLI/Command.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD/CLI/Command.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD/CLI/Command.pm Thu Nov 6 01:48:55 2008
@@ -50,7 +50,8 @@
if (my $footer = $args{footer}) {
$text .= $footer;
}
- $content = $self->edit_text($text);
+
+ $content = $self->edit_text($text);
# user aborted their text editor without changing anything; signify
# this to the caller by returning nothing
$content = '' if $content eq $text;
Modified: sd/branches/init-and-clone/lib/App/SD/CLI/Command/Help.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD/CLI/Command/Help.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD/CLI/Command/Help.pm Thu Nov 6 01:48:55 2008
@@ -43,6 +43,7 @@
$cmd help attachments - Working with ticket attachments
$cmd help sync - Publishing and importing ticket databases
$cmd help environment - Environment variables which affect sd
+$cmd help config - Database configuration variables
EOF
Added: sd/branches/init-and-clone/lib/App/SD/CLI/Command/Help/Config.pm
==============================================================================
--- (empty file)
+++ sd/branches/init-and-clone/lib/App/SD/CLI/Command/Help/Config.pm Thu Nov 6 01:48:55 2008
@@ -0,0 +1,30 @@
+package App::SD::CLI::Command::Help::Config;
+use Moose;
+extends 'App::SD::CLI::Command::Help';
+
+sub run {
+ my $self = shift;
+ $self->print_header('Configuration Options');
+
+print <<EOF
+ SD supports both a user-wide configuration (\$HOME/.sdrc and per-database
+ configuration (/path/to/repo/sdrc). If both configuration files are present,
+ the database-specific config file will be used.
+
+ Currently, the following configuration variables are available:
+
+ reporter_email = foo\@bar.com
+ Specifies an email address to use as the default for tickets'
+ reported_by field.
+
+ summary_format_ticket = %4s },\$luid | %-11.11s,status | %-60.60s,summary
+ Specifies how to format ticket summaries (when listing tickets, e.g.).
+EOF
+
+}
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;
+
Modified: sd/branches/init-and-clone/lib/App/SD/CLI/Command/Help/Environment.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD/CLI/Command/Help/Environment.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD/CLI/Command/Help/Environment.pm Thu Nov 6 01:48:55 2008
@@ -9,6 +9,9 @@
print <<EOF
export SD_REPO=/path/to/sd/replica
Specify where the ticket database SD is using should reside
+
+ export SD_CONFIG=/path/to/sd/config/file
+ Specify where the configuration file SD is using should reside
EOF
}
Modified: sd/branches/init-and-clone/lib/App/SD/CLI/Command/Ticket/Update.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD/CLI/Command/Ticket/Update.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD/CLI/Command/Ticket/Update.pm Thu Nov 6 01:48:55 2008
@@ -14,7 +14,7 @@
my $self = shift;
$self->require_uuid;
my $record = $self->_load_record;
- return super() if (@{$self->prop_set} && !$self->has_arg('edit'));
+ return super() if ($self->context->prop_names && !$self->has_arg('edit'));
my $template_to_edit = $self->create_record_template($record);
my $done = 0;
Modified: sd/branches/init-and-clone/lib/App/SD/CLI/Dispatcher.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD/CLI/Dispatcher.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD/CLI/Dispatcher.pm Thu Nov 6 01:48:55 2008
@@ -1,67 +1,102 @@
#!/usr/bin/env perl
package App::SD::CLI::Dispatcher;
-use strict;
-use warnings;
use Prophet::CLI::Dispatcher -base;
+use Moose;
-
-on qr'^\?(.*)$' => sub {my $cmd = $1 || ''; run ('help'. $cmd, @_); last_rule;};
+# "sd ?about" => "sd help about"
+rewrite qr/^\?(.*)/ => sub { "help $1" };
# 'sd about' -> 'sd help about', 'sd copying' -> 'sd help copying'
-on qr'^(about|copying)$' => sub { run('help '.$1, @_); last_rule;};
-on qr'^help (?:push|pull|publish|server)$' => sub { run('help sync', @_); last_rule;};
-on qr'^help (?:env)$' => sub { run('help environment', @_); last_rule;};
-on qr'^help (?:ticket)$' => sub { run('help tickets', @_); last_rule;};
-on qr'^help ticket (list|search|find)$' => sub { run('help search', @_); last_rule;};
-on qr'^help (?:list|find)$' => sub { run('help search', @_); last_rule;};
-
-on qr{ticket \s+ give \s+ (.*) \s+ (.*)}xi => sub {
- my %args = @_;
- $args{context}->set_arg(type => 'ticket');
- $args{context}->set_arg(id => $1);
- $args{context}->set_arg(owner => $2);
- run('update', %args);
+rewrite [ ['about', 'copying'] ] => sub { "help $1" };
+
+under help => sub {
+ on about => run_command('Help::About');
+ on config => run_command('Help::Config');
+ on copying => run_command('Help::Copying');
+
+ on [ ['author', 'authors'] ] => run_command('Help::Authors');
+ on [ ['environment', 'env'] ] => run_command('Help::Environment');
+ on [ ['ticket', 'tickets'] ] => run_command('Help::Tickets');
+ on [ ['attachment', 'attachments'] ] => run_command('Help::Attachments');
+ on [ ['comment', 'comments'] ] => run_command('Help:::Comments');
+
+ on [
+ ['ticket', 'attachment', 'comment'],
+ ['list', 'search', 'find'],
+ ] => run_command('Help::Search');
+
+ on [ ['search', 'list', 'find'] ] => run_command('Help::Search');
+
+ on [ ['sync', 'push', 'pull', 'publish', 'server'] ]
+ => run_command('Help::Sync');
+};
+
+on help => run_command('Help');
+
+under ticket => sub {
+ on create => run_command('Ticket::Create');
+ on basics => run_command('Ticket::Basics');
+ on comments => run_command('Ticket::Comments');
+ on comment => run_command('Ticket::Comment');
+ on details => run_command('Ticket::Details');
+ on search => run_command('Ticket::Search');
+ on show => run_command('Ticket::Show');
+ on update => run_command('Ticket::Update');
+
+ on ['give', qr/.*/, qr/.*/] => sub {
+ my $self = shift;
+ $self->context->set_arg(id => $2);
+ $self->context->set_arg(owner => $3);
+ run('ticket update', $self, @_);
+ };
+
+ on [ ['resolve', 'close'] ] => sub {
+ my $self = shift;
+ $self->context->set_prop(status => 'closed');
+ run('ticket update', $self, @_);
+ };
+
+ under comment => sub {
+ on create => run_command('Ticket::Comment::Create');
+ on update => run_command('Ticket::Comment::Update');
+ };
+
+ under attachment => sub {
+ on create => run_command('Ticket::Attachment::Create');
+ on search => run_command('Ticket::Attachment::Search');
+ };
+};
+
+under attachment => sub {
+ on content => run_command('Attachment::Content');
+ on create => run_command('Attachment::Create');
};
# allow type to be specified via primary commands, e.g.
# 'sd ticket display --id 14' -> 'sd display --type ticket --id 14'
on qr{^(ticket|comment|attachment) \s+ (.*)}xi => sub {
- my %args = @_;
- $args{context}->set_arg(type => $1);
- run($2, %args);
+ my $self = shift;
+ $self->context->set_arg(type => $1);
+ run($2, $self, @_);
};
-#on qr'^about$' => sub { run('help about'); last_rule;};
+__PACKAGE__->dispatcher->add_rule(
+ Path::Dispatcher::Rule::Dispatch->new(
+ dispatcher => Prophet::CLI::Dispatcher->dispatcher,
+ ),
+);
+
+sub run_command { Prophet::CLI::Dispatcher::run_command(@_) }
+
+sub class_names {
+ my $self = shift;
+ my $name = shift;
+ ("App::SD::CLI::Command::$name", $self->SUPER::class_names($name, @_));
+}
-# Run class based commands
-on qr{.} => sub {
- my %args = @_;
- my $cli = $args{cli};
-
- my @possible_classes;
-
- # we want to dispatch on the original command "ticket attachment create"
- # AND on the command we received "create"
- for ([@{ $args{dispatching_on} }], [split ' ', $_]) {
- my @pieces = __PACKAGE__->resolve_builtin_aliases(@$_);
-
- while (@pieces) {
- push @possible_classes, "App::SD::CLI::Command::" . join '::', @pieces;
- shift @pieces;
- }
- }
-
- for my $class (@possible_classes) {
- if ($args{cli}->_try_to_load_cmd_class($class)) {
- return $args{got_command}->($class)
- }
- }
-
- # found no class-based rule
- next_rule;
-};
-
+__PACKAGE__->meta->make_immutable;
+no Moose;
1;
Modified: sd/branches/init-and-clone/lib/App/SD/CLI/Model/Ticket.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD/CLI/Model/Ticket.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD/CLI/Model/Ticket.pm Thu Nov 6 01:48:55 2008
@@ -160,7 +160,7 @@
# glue all the parts together
return join(
- "\n\n",
+ "\n",
$self->_build_template_section(
header => metadata_separator,
Added: sd/branches/init-and-clone/lib/App/SD/Config.pm
==============================================================================
--- (empty file)
+++ sd/branches/init-and-clone/lib/App/SD/Config.pm Thu Nov 6 01:48:55 2008
@@ -0,0 +1,34 @@
+package App::SD::Config;
+use Moose;
+use File::Spec;
+
+extends 'Prophet::Config';
+
+# We can't just frob $ENV{PROPHET_APP_CONFIG} the way the sd script does
+# with $ENV{PROPHET_REPO} because we need to instantiate App::SD::CLI to
+# get the location of the repo root, and then Prophet would load its own
+# config file before we got around to messing with the env var
+before 'app_config_file' => sub {
+ my $self = shift;
+
+ # The order of preference for config files is:
+ # $ENV{SD_CONFIG} > fs_root/sdrc > fs_root/prophetrc (for backcompat)
+ # $HOME/.sdrc > $ENV{PROPHET_APP_CONFIG} > $HOME/.prophetrc
+
+ $ENV{'PROPHET_APP_CONFIG'}
+ = $self->file_if_exists($ENV{'SD_CONFIG'})
+ || $self->file_if_exists(
+ File::Spec->catfile($self->app_handle->handle->fs_root => 'sdrc'))
+ || $self->file_if_exists(
+ # backcompat
+ File::Spec->catfile($self->app_handle->handle->fs_root => 'prophetrc'))
+ || $self->file_if_exists(
+ File::Spec->catfile($ENV{'HOME'}.'/.sdrc'))
+ || $ENV{'PROPHET_APP_CONFIG'} # don't overwrite with nothing
+ || ''; # don't write undef
+};
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;
Modified: sd/branches/init-and-clone/lib/App/SD/Model/Ticket.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD/Model/Ticket.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD/Model/Ticket.pm Thu Nov 6 01:48:55 2008
@@ -34,7 +34,7 @@
=cut
sub default_prop_reported_by {
- shift->app_handle->config->{reporter_email} or $ENV{EMAIL}
+ shift->app_handle->config->get('reporter_email') or $ENV{EMAIL}
}
=head2 canonicalize_prop_status
Modified: sd/branches/init-and-clone/lib/App/SD/Replica/hm.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD/Replica/hm.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD/Replica/hm.pm Thu Nov 6 01:48:55 2008
@@ -27,7 +27,6 @@
sub BUILD {
my $self = shift;
-
require Net::Jifty;
my ($server, $props) = $self->{url} =~ m/^hm:(.*?)(?:\|(.*))?$/
or die "Can't parse Hiveminder server spec. Expected hm:http://hiveminder.com or hm:http://hiveminder.com|props";
@@ -39,13 +38,12 @@
$uri->userinfo(undef);
}
$self->remote_url("$uri");
+ $self->hm_username($username);
( $username, $password ) = $self->prompt_for_login( $uri, $username ) unless $password;
-
if ( $props ) {
my %props = split /=|;/, $props;
$self->props( \%props );
}
-
$self->hm(
Net::Jifty->new(
site => $self->remote_url,
@@ -55,18 +53,17 @@
password => $password
)
);
-
- $self->hm_username($username);
}
=head2 uuid
-Return the replica SVN repository's UUID
+Return the replica's UUID
=cut
sub uuid {
my $self = shift;
+ Carp::cluck "- can't make a uuid for this" unless ($self->remote_url && $self->hm_username);
return $self->uuid_for_url( join( '/', $self->remote_url, $self->hm_username ) );
}
@@ -96,17 +93,15 @@
sub find_matching_tasks {
my $self = shift;
- my %args = (
- owner => 'me',
- group => 0,
- requestor => 'me',
- not_complete => 1,
- );
+ my %args;
if ( my $props = $self->props ) {
while ( my ($k, $v) = each %$props ) { $args{$k} = $v }
}
- my $tasks = $self->hm->act( 'TaskSearch', %args )->{content}->{tasks};
- return $tasks;
+ my $status = $self->hm->act( 'TaskSearch', %args );
+ unless ( $status->{'success'} ) {
+ die "couldn't search";
+ }
+ return $status->{content}{tasks};
}
sub record_pushed_transactions {
Modified: sd/branches/init-and-clone/lib/App/SD/Replica/hm/PushEncoder.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD/Replica/hm/PushEncoder.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD/Replica/hm/PushEncoder.pm Thu Nov 6 01:48:55 2008
@@ -68,6 +68,9 @@
repeat_stacking => 0,
%{ $self->_recode_props_for_create($change) }
);
+ unless ( $task->{'success'} ) {
+ die "Couldn't create a task: ". $self->decode_error( $task );
+ }
my $txns = $self->sync_source->hm->search( 'TaskTransaction', task_id => $task->{content}->{id} );
@@ -76,6 +79,19 @@
return $task->{content}->{id};
}
+sub decode_error {
+ my $self = shift;
+ my $status = shift;
+ my $msg = '';
+ $msg .= $status->{'error'} if defined $status->{'error'};
+ if ( $status->{'field_errors'} ) {
+ while ( my ($k, $v) = each %{ $status->{'field_errors'} } ) {
+ $msg .= "field '$k' - '$v'\n";
+ }
+ }
+ return $msg;
+}
+
sub integrate_comment {
my $self = shift;
my ($change, $changeset) = validate_pos( @_, { isa => 'Prophet::Change' }, {isa => 'Prophet::ChangeSet'} );
@@ -93,7 +109,7 @@
);
return $status->{'content'}{'id'} if $status->{'success'};
- die "Couldn't integrate comment: ". $status->{'error'};
+ die "Couldn't integrate comment: ". $self->decode_error( $status );
}
sub integrate_ticket_update {
@@ -113,7 +129,7 @@
);
return $status->{'content'}{'id'} if $status->{'success'};
- die "Couldn't integrate comment: ". $status->{'error'};
+ die "Couldn't integrate comment: ". $self->decode_error( $status );
}
sub _recode_props_for_create {
Modified: sd/branches/init-and-clone/lib/App/SD/Replica/rt/PullEncoder.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD/Replica/rt/PullEncoder.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD/Replica/rt/PullEncoder.pm Thu Nov 6 01:48:55 2008
@@ -144,39 +144,41 @@
sub transcode_one_txn {
my ($self, $txn, $ticket) = (@_);
- if ( my $sub = $self->can( '_recode_txn_' . $txn->{'Type'} ) ) {
- my $changeset = Prophet::ChangeSet->new(
- { original_source_uuid => $self->sync_source->uuid,
- original_sequence_no => $txn->{'id'},
- creator => $self->resolve_user_id_to( email_address => $txn->{'Creator'} ),
- }
- );
-
- if ( ( $txn->{'Ticket'} ne $ticket->{$self->sync_source->uuid . '-id'} ) && $txn->{'Type'} !~ /^(?:Comment|Correspond)$/ ) {
- warn "Skipping a data change from a merged ticket" . $txn->{'Ticket'} . ' vs ' . $ticket->{$self->sync_source->uuid . '-id'};
- next;
- }
-
+ my $sub = $self->can( '_recode_txn_' . $txn->{'Type'} );
+ unless ( $sub ) {
+ die "Transaction type $txn->{Type} (for transaction $txn->{id}) not implemented yet";
+ }
+ my $changeset = Prophet::ChangeSet->new(
+ { original_source_uuid => $self->sync_source->uuid,
+ original_sequence_no => $txn->{'id'},
+ creator => $self->resolve_user_id_to( email_address => $txn->{'Creator'} ),
+ }
+ );
- delete $txn->{'OldValue'} if ( $txn->{'OldValue'} eq '');
- delete $txn->{'NewValue'} if ( $txn->{'NewValue'} eq '');
+ if ( $txn->{'Ticket'} ne $ticket->{$self->sync_source->uuid . '-id'}
+ && $txn->{'Type'} !~ /^(?:Comment|Correspond)$/
+ ) {
+ warn "Skipping a data change from a merged ticket" . $txn->{'Ticket'}
+ .' vs '. $ticket->{$self->sync_source->uuid . '-id'};
+ next;
+ }
- $sub->( $self, ticket => $ticket, txn => $txn, changeset => $changeset);
- $self->translate_prop_names($changeset);
+ delete $txn->{'OldValue'} if ( $txn->{'OldValue'} eq '');
+ delete $txn->{'NewValue'} if ( $txn->{'NewValue'} eq '');
- if (my $attachments = delete $txn->{'_attachments'}) {
- for my $attach (@$attachments) {
- $self->_recode_attachment_create( ticket => $ticket, txn => $txn, changeset =>$changeset, attachment => $attach);
- }
- }
+ $sub->( $self, ticket => $ticket, txn => $txn, changeset => $changeset);
+ $self->translate_prop_names($changeset);
- return $changeset;
- } else {
- die "Transaction type $txn->{Type} (for transaction $txn->{id}) not implemented yet";
- }
+ if (my $attachments = delete $txn->{'_attachments'}) {
+ for my $attach (@$attachments) {
+ $self->_recode_attachment_create( ticket => $ticket, txn => $txn, changeset =>$changeset, attachment => $attach);
+ }
}
+ return $changeset;
+}
+
sub _recode_attachment_create {
my $self = shift;
@@ -227,39 +229,34 @@
my %args = validate( @_, { txn => 1, ticket => 1, changeset => 1 } );
my $change = Prophet::Change->new(
- { record_type => 'ticket',
- record_uuid => $self->sync_source->uuid_for_remote_id( $args{'ticket'}->{$self->sync_source->uuid . '-id'} ),
+ { record_type => 'ticket',
+ record_uuid => $self->sync_source->uuid_for_remote_id( $args{'ticket'}->{$self->sync_source->uuid . '-id'} ),
change_type => 'update_file'
}
);
- if ( $args{txn}->{Field} eq 'Queue' ) {
+ my ($field, $old, $new) = @{ $args{txn} }{qw(Field OldValue NewValue)};
+
+ if ( $field eq 'Queue' ) {
my $current_queue = $args{'ticket'}->{$self->sync_source->uuid .'-queue'};
my $user = $args{txn}->{Creator};
if ( $args{txn}->{Description} =~ /Queue changed from (.*) to $current_queue by $user/ ) {
- $args{txn}->{OldValue} = $1;
- $args{txn}->{NewValue} = $current_queue;
+ $old = $1;
+ $new = $current_queue;
}
- } elsif ( $args{txn}->{Field} eq 'Owner' ) {
- $args{'txn'}->{NewValue} = $self->resolve_user_id_to( name => $args{'txn'}->{'NewValue'} );
- $args{'txn'}->{OldValue} = $self->resolve_user_id_to( name => $args{'txn'}->{'OldValue'} );
+ } elsif ( $field eq 'Owner' ) {
+ $new = $self->resolve_user_id_to( email_address => $new );
+ $old = $self->resolve_user_id_to( email_address => $old );
}
$args{'changeset'}->add_change( { change => $change } );
- if ( $args{'ticket'}->{ $args{txn}->{Field} } eq $args{txn}->{'NewValue'} ) {
- $args{'ticket'}->{ $args{txn}->{Field} } = $args{txn}->{'OldValue'};
- } else {
- $args{'ticket'}->{ $args{txn}->{Field} } = $args{txn}->{'OldValue'};
- warn "Update consistency problem: " . $args{'ticket'}->{ $args{txn}->{Field} } . " != " . $args{txn}->{'NewValue'};
- }
- $change->add_prop_change(
- name => $args{txn}->{'Field'},
- old => $args{txn}->{'OldValue'},
- new => $args{txn}->{'NewValue'}
-
- );
+
+ # XXX: This line is kind of magic
+ # TODO: check if it's sill needed
+ $args{'ticket'}->{ $field } = $old;
+ $change->add_prop_change( name => $field, old => $old, new => $new );
}
*_recode_txn_Steal = \&_recode_txn_Set;
@@ -418,15 +415,23 @@
my $self = shift;
my $attr = shift;
my $id = shift;
- return undef unless ($id);
+ return undef unless $id;
+ local $@;
my $user = eval { RT::Client::REST::User->new( rt => $self->sync_source->rt, id => $id )->retrieve};
- if (my $err = $@) {
- warn $err;
- return $attr eq 'name' ? 'Unknown user' : 'nobody at localhost';
- }
- return $user->$attr();
-
+ if ( my $err = $@ ) {
+ warn $err;
+ return $attr eq 'name' ? 'Unknown user' : 'unknown at localhost';
+ }
+ my $name = $user->name;
+ if ( lc $name eq 'nobody' ) {
+ return $attr eq 'name' ? 'nobody' : undef;
+ }
+ elsif ( lc $name eq 'RT_System' ) {
+ return $attr eq 'name' ? 'system' : undef;
+ } else {
+ return $user->$attr();
+ }
}
memoize 'resolve_user_id_to';
Modified: sd/branches/init-and-clone/lib/App/SD/Test.pm
==============================================================================
--- sd/branches/init-and-clone/lib/App/SD/Test.pm (original)
+++ sd/branches/init-and-clone/lib/App/SD/Test.pm Thu Nov 6 01:48:55 2008
@@ -8,9 +8,10 @@
use File::Spec;
use Cwd qw/getcwd/;
use base qw/Exporter/;
-our @EXPORT = qw(create_ticket_ok create_ticket_comment_ok get_uuid_for_luid get_luid_for_uuid);
-$ENV{'EMAIL'} = "someone\@example.com";
-$ENV{'PROPHET_APP_CONFIG'} = "t/prophet_testing.conf";
+our @EXPORT = qw(create_ticket_ok create_ticket_with_editor_ok create_ticket_comment_ok get_uuid_for_luid get_luid_for_uuid);
+$ENV{'SD_CONFIG'} = 't/prophet_testing.conf';
+delete $ENV{'PROPHET_APP_CONFIG'};
+$ENV{'EDITOR'} = '/bin/true';
=head2 create_ticket_ok ARGS
@@ -101,7 +102,8 @@
my ( $ticket_uuid, $ticket_luid, $comment_uuid, $comment_luid );
local $Test::Builder::Level = $Test::Builder::Level + 1;
Prophet::Test::run_output_matches( 'sd', [ 'ticket', 'create' ],
- [qr/Created ticket (.*?)(?{ $ticket_luid = $1})\s+\((.*)(?{ $ticket_uuid = $2 })\)/, qr/Created comment (.*?)(?{ $comment_luid = $1})\s+\((.*)(?{ $comment_uuid = $2 })\)/]
+ [qr/Created ticket (.*?)(?{ $ticket_luid = $1})\s+\((.*)(?{ $ticket_uuid = $2 })\)/,
+ qr/Created comment (.*?)(?{ $comment_luid = $1})\s+\((.*)(?{ $comment_uuid = $2 })\)/]
);
return ( $ticket_luid, $ticket_uuid, $comment_luid, $comment_uuid );
@@ -168,3 +170,20 @@
$ENV{'EDITOR'} = File::Spec->catfile(getcwd(), 't', 'scripts', $script);
diag 'export EDITOR=' . $ENV{'EDITOR'} . "\n";
}
+
+=head2 write_to_file FILENAME DATA
+
+Takes the string given in DATA and writes it to the file whose name is given
+by FILENAME.
+
+=cut
+
+sub write_to_file {
+ my ($self, $filename, $data) = @_;
+
+ open FH, '>', $filename;
+ print FH $data;
+ close FH;
+}
+
+1;
Modified: sd/branches/init-and-clone/t/01-create.t
==============================================================================
--- sd/branches/init-and-clone/t/01-create.t (original)
+++ sd/branches/init-and-clone/t/01-create.t Thu Nov 6 01:48:55 2008
@@ -34,7 +34,6 @@
'status: new',
qr/^created: \d{4}-\d{2}-\d{2}.+$/,
qr/^creator: /,
- qr/^reported_by: /,
'milestone: alpha',
"original_replica: " . replica_uuid,
]
Modified: sd/branches/init-and-clone/t/02-create-with-editor.t
==============================================================================
--- sd/branches/init-and-clone/t/02-create-with-editor.t (original)
+++ sd/branches/init-and-clone/t/02-create-with-editor.t Thu Nov 6 01:48:55 2008
@@ -13,7 +13,7 @@
run_script( 'sd', [ 'init']);
my $replica_uuid = replica_uuid;
-my ($ticket_id, $ticket_uuid, $comment_id, $comment_uuid) = App::SD::Test::create_ticket_with_editor_ok();
+my ($ticket_id, $ticket_uuid, $comment_id, $comment_uuid) = create_ticket_with_editor_ok();
run_output_matches( 'sd', [ 'ticket',
'list', '--regex', '.' ],
@@ -27,7 +27,6 @@
'status: new',
qr/^created: \d{4}-\d{2}-\d{2}.+$/,
qr/^creator: /,
- qr/^reported_by: /,
'milestone: alpha',
"original_replica: $replica_uuid",
]
Modified: sd/branches/init-and-clone/t/03-update-ticket-with-editor.t
==============================================================================
--- sd/branches/init-and-clone/t/03-update-ticket-with-editor.t (original)
+++ sd/branches/init-and-clone/t/03-update-ticket-with-editor.t Thu Nov 6 01:48:55 2008
@@ -27,7 +27,6 @@
'owner: foo at bar.com',
qr/^created: \d{4}-\d{2}-\d{2}.+$/,
qr/^creator: /,
- qr/^reported_by: /,
'milestone: alpha',
"original_replica: $replica_uuid",
]
@@ -44,7 +43,6 @@
'status: new',
qr/^created: \d{4}-\d{2}-\d{2}.+$/,
qr/^creator: /,
- qr/^reported_by: /,
'milestone: alpha',
"original_replica: $replica_uuid",
]
Added: sd/branches/init-and-clone/t/05-config-file-loading.t
==============================================================================
--- (empty file)
+++ sd/branches/init-and-clone/t/05-config-file-loading.t Thu Nov 6 01:48:55 2008
@@ -0,0 +1,113 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+use Prophet::Test tests => 10;
+use App::SD::Test;
+use File::Temp qw/tempdir/;
+use Path::Class;
+
+
+no warnings 'once';
+
+BEGIN {
+ require File::Temp;
+ $ENV{'PROPHET_REPO'} = $ENV{'SD_REPO'} = $ENV{'HOME'} = File::Temp::tempdir( CLEANUP => 0 ) . '/_svb';
+ diag "export SD_REPO=".$ENV{'PROPHET_REPO'} ."\n";
+ diag "export HOME=".$ENV{'PROPHET_REPO'} ."\n";
+ $ENV{'PROPHET_APP_CONFIG'} = undef; # clear this because Prophet::Test sets it
+}
+
+# Tests the config file order of preference laid out in App::SD::Config
+run_script( 'sd', [ 'init']);
+
+
+
+# create from sd
+my ($yatta_id, $yatta_uuid) = create_ticket_ok( '--summary', 'YATTA');
+
+# default config file
+diag("Testing default config file\n");
+
+run_output_matches( 'sd', [ 'ticket',
+ 'list', '--regex', '.' ],
+ [ qr/(\d+) YATTA new/]
+);
+
+$ENV{'SD_CONFIG'} = $ENV{'PROPHET_APP_CONFIG'} = undef; # override App::SD::Test
+ok( ! $ENV{'SD_CONFIG'}, "SD_CONFIG env var has been cleared" );
+ok( ! $ENV{'PROPHET_APP_CONFIG'}, "PROPHET_APP_CONFIG env var has been cleared" );
+
+# Test from least-preferred to most preferred, leaving the least-preferred
+# files in place to make sure the next-most-preferred file is preferred
+# over all the files beneath it.
+
+diag("Testing \$HOME/.prophetrc\n");
+
+my $config_filename = $ENV{'HOME'} . '/.prophetrc';
+
+App::SD::Test->write_to_file($config_filename,
+ "summary_format_ticket = %4s },\$luid | %-11.11s,status | %-60.60s,summary\n");
+
+run_output_matches( 'sd', [ 'ticket',
+ 'list', '--regex', '.' ],
+ [ qr/\s+(\d+) } new YATTA/]
+);
+
+diag("Testing PROPHET_APP_CONFIG\n");
+
+$config_filename = $ENV{'HOME'} . '/config-test';
+$ENV{'PROPHET_APP_CONFIG'} = $config_filename;
+
+App::SD::Test->write_to_file($config_filename,
+ "summary_format_ticket = %-9.9s,status | %-60.60s,summary\n");
+
+run_output_matches( 'sd', [ 'ticket',
+ 'list', '--regex', '.' ],
+ [ qr/new YATTA/]
+);
+
+diag("Testing \$HOME/.sdrc\n");
+
+$config_filename = $ENV{'HOME'} . '/.sdrc';
+
+App::SD::Test->write_to_file($config_filename,
+ "summary_format_ticket = %4s },\$luid | %-7.7s,status | %-60.60s,summary\n");
+
+run_output_matches( 'sd', [ 'ticket',
+ 'list', '--regex', '.' ],
+ [ qr/\s+(\d+) } new YATTA/]
+);
+
+diag("Testing fs_root/prophetrc\n");
+
+$config_filename = $ENV{'SD_REPO'} . '/prophetrc';
+
+App::SD::Test->write_to_file($config_filename,
+ "summary_format_ticket = %4s },\$luid | %-10.10s,status | %-60.60s,summary\n");
+
+run_output_matches( 'sd', [ 'ticket',
+ 'list', '--regex', '.' ],
+ [ qr/\s+(\d+) } new YATTA/]
+);
+
+diag("Testing fs_root/sdrc\n");
+
+$config_filename = $ENV{'SD_REPO'} . '/sdrc';
+
+App::SD::Test->write_to_file($config_filename,
+ "summary_format_ticket = %4s },\$luid | %-6.6s,status | %-60.60s,summary\n");
+
+run_output_matches( 'sd', [ 'ticket',
+ 'list', '--regex', '.' ],
+ [ qr/\s+(\d+) } new YATTA/]
+);
+
+diag("Testing SD_CONFIG\n");
+
+$ENV{'SD_CONFIG'} = 't/prophet_testing.conf';
+
+run_output_matches( 'sd', [ 'ticket',
+ 'list', '--regex', '.' ],
+ [ qr/(\d+) YATTA new/]
+);
Modified: sd/branches/init-and-clone/t/sd-comments.t
==============================================================================
--- sd/branches/init-and-clone/t/sd-comments.t (original)
+++ sd/branches/init-and-clone/t/sd-comments.t Thu Nov 6 01:48:55 2008
@@ -2,7 +2,7 @@
use strict;
-use Prophet::Test tests => 8;
+use Prophet::Test tests => 10;
use App::SD::Test;
no warnings 'once';
@@ -48,6 +48,7 @@
[],
"Found the comment"
);
+
run_output_matches(
'sd',
[ qw/ticket comment update --uuid/, $comment_uuid,
@@ -58,6 +59,7 @@
[],
"updated the comment"
);
+
run_output_matches(
'sd',
[ qw/ticket comment show --batch --uuid/, $comment_uuid ],
@@ -79,3 +81,30 @@
[],
"Found the comment when we tried to search for all comments on a ticket by the ticket's uuid"
);
+
+run_output_matches(
+ 'sd',
+ [ qw/ticket comment update --uuid/, $comment_uuid,
+ '--',
+ qw/--content/, "A\nmultiline\ncomment"
+ ],
+ [qr/comment \d+ \($comment_uuid\) updated/],
+ [],
+ "updated the comment to a multiline content"
+);
+
+run_output_matches(
+ 'sd',
+ [ qw/ticket comment show --batch --uuid/, $comment_uuid ],
+ [ qr/id: (\d+) \($comment_uuid\)/,
+ qr/^content: A/,
+ qr/^multiline$/,
+ qr/^comment$/,
+ qr/created: /i,
+ qr/creator: /i,
+ "original_replica: $replica_uuid",
+ "ticket: $yatta_uuid"
+ ],
+ [],
+ "Found the comment new version"
+);
Modified: sd/branches/init-and-clone/t/sd-hm-comments.t
==============================================================================
--- sd/branches/init-and-clone/t/sd-hm-comments.t (original)
+++ sd/branches/init-and-clone/t/sd-hm-comments.t Thu Nov 6 01:48:55 2008
@@ -41,7 +41,6 @@
my ($yatta_uuid, $yatta_id);
{
my ($ret, $out, $err) = run_script( 'sd', [ 'clone', '--from', $sd_hm_url ] );
-
run_output_matches( 'sd', [qw(ticket list --regex .)], [qr/(.*?)(?{ $yatta_uuid = $1 }) YATTA (.*)/] );
( $ret, $out, $err ) = run_script( 'sd', [ qw(ticket show --batch --id), $yatta_uuid ] );
$yatta_id = $1 if $out =~ /^id: (\d+) /m;
Modified: sd/branches/init-and-clone/t/sd-hm-comments1.t
==============================================================================
--- sd/branches/init-and-clone/t/sd-hm-comments1.t (original)
+++ sd/branches/init-and-clone/t/sd-hm-comments1.t Thu Nov 6 01:48:55 2008
@@ -35,6 +35,8 @@
my $sd_hm_url = "hm:$URL";
+run_script('sd', [qw(init)]);
+
my ($yatta_id, $yatta_uuid) = create_ticket_ok( qw(--summary YATTA --status new) );
{
my ( $ret, $out, $err ) = run_script( 'sd', [ 'push','--to', $sd_hm_url ] );
Modified: sd/branches/init-and-clone/t/sd-hm-group.t
==============================================================================
--- sd/branches/init-and-clone/t/sd-hm-group.t (original)
+++ sd/branches/init-and-clone/t/sd-hm-group.t Thu Nov 6 01:48:55 2008
@@ -66,8 +66,10 @@
# pull
{
- eval { ( $ret, $out, $err ) = run_script( 'sd', [ 'pull', '--from', $sd_hm_url ] ) };
+ eval { ( $ret, $out, $err ) = run_script( 'sd', [ 'clone', '--from', $sd_hm_url ] ) };
like($out, qr/one changeset/, "only one change");
+ diag($out);
+ diag($err);
}
my ($flyman_uuid, $flyman_id );
@@ -122,7 +124,7 @@
rmtree( $ENV{'SD_REPO'}, {keep_root => 1} );
-my $sd_hm_url = "hm:$URL|group=$gname";
+$sd_hm_url = "hm:$URL|group=$gname";
# pull
{
eval { ( $ret, $out, $err ) = run_script( 'sd', [ 'pull', '--from', $sd_hm_url ] ) };
Modified: sd/branches/init-and-clone/t/sd-hm-tag.t
==============================================================================
--- sd/branches/init-and-clone/t/sd-hm-tag.t (original)
+++ sd/branches/init-and-clone/t/sd-hm-tag.t Thu Nov 6 01:48:55 2008
@@ -54,7 +54,7 @@
my ( $ret, $out, $err );
my $sd_hm_url = "hm:$URL|tag=mytag";
-eval { ( $ret, $out, $err ) = run_script( 'sd', [ 'pull', '--from', $sd_hm_url ] ) };
+eval { ( $ret, $out, $err ) = run_script( 'sd', [ 'clone', '--from', $sd_hm_url ] ) };
like($out, qr/one changeset/, "only one change");
my ($flyman_uuid, $flyman_id );
Modified: sd/branches/init-and-clone/t/sd-hm.t
==============================================================================
--- sd/branches/init-and-clone/t/sd-hm.t (original)
+++ sd/branches/init-and-clone/t/sd-hm.t Thu Nov 6 01:48:55 2008
@@ -42,7 +42,7 @@
my ( $ret, $out, $err );
my $sd_hm_url = "hm:$URL";
-eval { ( $ret, $out, $err ) = run_script( 'sd', [ 'pull', '--from', $sd_hm_url ] ) };
+eval { ( $ret, $out, $err ) = run_script( 'sd', [ 'clone', '--from', $sd_hm_url ] ) };
diag $err;
my ($flyman_uuid, $flyman_id );
Modified: sd/branches/init-and-clone/t/sd-rt-hm-single.t
==============================================================================
--- sd/branches/init-and-clone/t/sd-rt-hm-single.t (original)
+++ sd/branches/init-and-clone/t/sd-rt-hm-single.t Thu Nov 6 01:48:55 2008
@@ -82,7 +82,7 @@
as_bob {
local $ENV{SD_REPO} = $ENV{'PROPHET_REPO'};
- ( $ret, $out, $err ) = run_script( 'sd', [ 'pull', '--from', $sd_hm_url ] );
+ ( $ret, $out, $err ) = run_script( 'sd', [ 'clone', '--from', $sd_hm_url ] );
diag($err) if ($err);
run_output_matches( 'sd', [ 'ticket', 'list', '--regex', '.' ], [qr/^(.*?)(?{ $yatta_id = $1 }) YATTA .*/] );
$yatta_uuid = get_uuid_for_luid($yatta_id);
Modified: sd/branches/init-and-clone/t/sd-rt-permission.t
==============================================================================
--- sd/branches/init-and-clone/t/sd-rt-permission.t (original)
+++ sd/branches/init-and-clone/t/sd-rt-permission.t Thu Nov 6 01:48:55 2008
@@ -19,6 +19,7 @@
require File::Temp;
$ENV{'PROPHET_REPO'} = $ENV{'SD_REPO'} = File::Temp::tempdir( CLEANUP => 0 ) . '/_svb';
diag "export SD_REPO=".$ENV{'PROPHET_REPO'} ."\n";
+
}
use Prophet::Test tests => 22;
@@ -64,7 +65,7 @@
as_alice {
run_script( 'sd', [ 'init']);
- ($ret, $out, $err) = run_script('sd', ['pull', '--from', $sd_alice_url]);
+ ($ret, $out, $err) = run_script('sd', ['pull', '--from', $sd_alice_url, '--force']);
ok($ret);
like($out, qr/No new changesets/);
Modified: sd/branches/init-and-clone/t/sd-rt.t
==============================================================================
--- sd/branches/init-and-clone/t/sd-rt.t (original)
+++ sd/branches/init-and-clone/t/sd-rt.t Thu Nov 6 01:48:55 2008
@@ -51,7 +51,7 @@
)->store( text => "Ticket Comment" );
my ( $ret, $out, $err );
-( $ret, $out, $err ) = run_script( 'sd', [ 'pull', '--from', $sd_rt_url ] );
+( $ret, $out, $err ) = run_script( 'sd', [ 'clone', '--from', $sd_rt_url ] );
my ( $yatta_id, $flyman_id );
run_output_matches( 'sd', [ 'ticket', 'list', '--regex', '.' ],
[qr/(.*?)(?{ $flyman_id = $1 }) Fly Man new/] );
@@ -77,6 +77,8 @@
run_output_matches_unordered( 'sd', [ 'ticket', 'list', '--regex', '.' ], [sort "$yatta_id YATTA new", "$flyman_id Fly Man open" ]);
( $ret, $out, $err ) = run_script( 'sd', [ 'push', '--to', $sd_rt_url ] );
+diag ($out);
+diag ($err);
my @tix = $rt->search(
type => 'ticket',
query => "Subject='YATTA'"
More information about the Bps-public-commit
mailing list