#!/usr/bin/env perl

# Some tests for the '--match' flag

use lib qw(lib/perl);

use Test::More qw/no_plan/;

use Test::Darcs;
use Shell::Command;

use strict;

# matching by date

cleanup  'tmp';
mkpath 'tmp';
chdir  'tmp';
darcs 'init';
touch 'bar';
darcs qw( add bar );
darcs qw( record -a -m "" bar -A x );

sub try_date {
  my $d = shift;
  # just be happy if it doesn't complain about the date being fancy
  unlike( darcs("changes --match='date $d'"), qr(fancy), "match on $d" );
}

# FIXME: for now we only check for recognition, not for a correct parse!

# the comments about dates being the same are meant for some brave soul
# willing to implement more semantic tests

# alternately, it might be more useful to build a random date string generator
# using QuickCheck... for any n random CalendarTimes, have it generate some
# possible variants and roundtrip them to see if they match

# this block of dates should all refer to the same thing
try_date '2007-01-01';
try_date '20070101';
try_date '2007-01';
try_date '200701';
try_date '2007';
# week dates. note that 2007 was tactically selected as it starts on Monday
try_date '2007-W01-1';
try_date '2007W011';
try_date '2007-W01';
# ordinal dates. eh... why not?
try_date '2007-001'; # first day of 2005
try_date '2007001';

# midnight and zero
try_date '1992-10-14 24:00';
try_date '1992-10-15 00:00';

# all the same date/time
try_date '1992-02-12T22:32:11';
try_date '1992-02-12 22:32:11';
try_date '1992-02-12T223211.0000';

# english dates - the old hard coded from < darcs 1.0.6
try_date 'today';
try_date 'yesterday';
try_date 'day before yesterday';
try_date 'last week';
try_date 'last month';

# english dates - new possibilities
try_date 'yesterday at 14:00:00';
try_date 'last 3 years';
try_date '2 days ago';
try_date 'last month 13:00' ;
try_date '15 minutes after 1992-10-02';
try_date '3 days before last week';

# english intervals
try_date 'between last fortnight and yesterday';
try_date 'in the last 45 seconds';
try_date 'after 1992';

# iso 8601 intervals
try_date '1992-10-15 00:00Z/1992-10-15 00:01Z';
try_date 'P3YT3M/1992';
try_date '1992/P3Y3M4DT5H3M2S';
try_date '1992/P3Y3M';

# stuff from the manual
try_date 'between 2004-03-12 and last week';
try_date 'last week';
try_date 'yesterday';
try_date 'today 14:00';
try_date '3 days before last year at 17:00';
try_date 'Sat Jun  30 11:31:30 EDT 2004';
try_date 'after 2005';
try_date 'in the last 3 weeks';
try_date 'P3M/2006-03-17';
try_date '2004-01-02/2006-03-17';
try_date 'P2M6D';

# cvs dates
try_date '2006/01/19 21:14:20 UTC';
try_date '2006/01/19 21:14:20 EST';
try_date '2006/01/19 21:14:20';

# -------------------------------------------------------------------
# matching on atomic stuff (other than date)
# -------------------------------------------------------------------

cleanup  'tmp';
mkpath 'tmp';
chdir  'tmp';
darcs 'init';
touch 'bar';
darcs qw( add bar );
darcs qw( record -a -m "first patch"  bar -A author1 );
`echo foo > bar`;
darcs qw( record -a -m "\"second\" \\ patch" bar -A author2 );
`echo blop > bar`;
darcs qw( record -a -m "second" bar -A author3 );

# matching on author really matches on that, and not something else
unlike(darcs(qw(changes --match='author "first patch"')), qr(.+));

{ # normal changes shows both authors and both names
  my $res = darcs qw( changes );
  like($res, qr(author1));
  like($res, qr(author2));
  like($res, qr(author3));
  like($res, qr(first patch));
  like($res, qr("second" \\ patch));
  like($res, qr(second));
}

{ # exact
  my $res = darcs qw( changes --match='exact second' );
  unlike ($res, qr(author1), 'does not find unrelated patch');
  unlike ($res, qr(author2), 'does not find similar patch');
  like   ($res, qr(author3), 'finds the patch');
}

{ # name
  my $res = darcs qw( changes --match='name second' );
  unlike ($res, qr(author1), 'does not find unrelated patch');
  like   ($res, qr(author2), 'finds one of the patches');
  like   ($res, qr(author3), 'finds the other patch');
}

{ # author
  my $res = darcs qw( changes --match='author author1');
  like   ($res, qr(author1));
  unlike ($res, qr(author2));
  unlike ($res, qr(author3));
}

{ #hash
  my $xml = darcs(qw(changes --xml-output --match='exact "\"second\" \ patch"'));
  if ($xml =~ /hash='(.*?)'/) {
    my $res = darcs "changes --match='hash $1'";
    unlike($res, qr(author1));
    like  ($res, qr(author2));
    unlike($res, qr(author3));
  } else {
    ok ( 0 );
  }
}

# -------------------------------------------------------------------
# matching on combinations
#
# uses the setup from the atomic patches
# -------------------------------------------------------------------

{ # or
  my $res = darcs(qw(changes --match='author author1 || author author2'));
  like  ($res, qr(author1));
  like  ($res, qr(author2));
  unlike($res, qr(author3));
}

{ # and
  my $res = darcs(qw(changes --match='name second && author author2'));
  unlike($res, qr(author1));
  like  ($res, qr(author2));
  unlike($res, qr(author3));
}

{ # not
  my $res = darcs(qw(changes --match='not name second'));
  like  ($res, qr(author1));
  unlike($res, qr(author2));
  unlike($res, qr(author3));
}

{ # grouping
  my $res = darcs(qw(changes --match='(not name second) || author author3'));
  like  ($res, qr(author1));
  unlike($res, qr(author2));
  like  ($res, qr(author3));
}



# cleanup
chdir '..';
cleanup 'tmp';
