File Coverage

blib/lib/CouchDB/Deploy/Process.pm
Criterion Covered Total %
statement 24 83 28.9
branch 0 22 0.0
condition 0 13 0.0
subroutine 8 13 61.5
pod 5 5 100.0
total 37 136 27.2


line stmt bran cond sub pod time code
1              
2             package CouchDB::Deploy::Process;
3              
4 2     2   40544 use strict;
  2         4  
  2         153  
5 2     2   11 use warnings;
  2         4  
  2         110  
6              
7             our $VERSION = $CouchDB::Deploy::VERSION;
8              
9 2     2   10 use Carp qw(confess);
  2         19  
  2         182  
10 2     2   1120 use CouchDB::Client;
  2         126801  
  2         64  
11 2     2   14 use File::Spec;
  2         5  
  2         66  
12 2     2   1914 use Data::Compare qw(Compare);
  2         25461  
  2         25  
13             *_SAME = \&Compare;
14              
15             sub new {
16 2     2 1 4 my $class = shift;
17 2         4 my $server = shift;
18 2         21 return bless {
19             server => $server,
20             client => CouchDB::Client->new(uri => $server),
21             }, $class;
22             }
23              
24             sub createDBUnlessExists {
25 0     0 1   my $self = shift;
26 0           my $dbName = shift;
27            
28 0 0         $dbName .= '/' unless $dbName =~ m{/$};
29 0 0         if (not $self->{client}->dbExists($dbName)) {
30 0           $self->{db} = $self->{client}->newDB($dbName)->create();
31 0           return 1;
32             }
33             else {
34 0           $self->{db} = $self->{client}->newDB($dbName);
35 0           return 0;
36             }
37             }
38              
39 2     2   11154 use Data::Dumper;
  2         6965  
  2         1513  
40             sub addDocumentUnlessExistsOrSame {
41 0     0 1   my $self = shift;
42 0           my $id = shift;
43 0   0       my $data = shift || {};
44 0   0       my $newAttach = shift || {};
45            
46 0           my $db = $self->{db};
47 0 0         if (not $db->docExists($id)) {
48 0           $db->newDoc($id, undef, $data, $newAttach)->create();
49 0           return 1;
50             }
51             else {
52 0           my $doc = $db->newDoc($id)->retrieve();
53 0           my $content = $doc->data;
54 0           my $origAttach = $doc->attachments;
55 0 0 0       if (keys %$origAttach and keys %$newAttach) {
56             # compare attachments only if the rest isn't already different
57 0 0         if (_SAME($content, $data)) {
58             # the length is not the same, the names are not the same, or the content types are not the same
59 0 0 0       if (
      0        
60 0           scalar(keys(%$origAttach)) != scalar(keys(%$newAttach)) or
61 0           grep({ not exists $origAttach->{$_} } keys %$newAttach) or
62             grep({ $origAttach->{$_}->{content_type} ne $newAttach->{$_}->{content_type} } keys %$newAttach)
63             ) {
64 0           return _UPDATE($doc, $data, $newAttach);
65             }
66             # we have to fall back to comparing content
67             else {
68 0           for my $att (keys %$newAttach) {
69 0           my $b64 = $newAttach->{$att}->{data};
70 0 0         if ($b64 ne $doc->toBase64($doc->fetchAttachment($att))) {
71 0           return _UPDATE($doc, $data, $newAttach);
72             }
73             }
74             }
75             }
76             else {
77 0           return _UPDATE($doc, $data, $newAttach);
78             }
79             }
80             else {
81 0 0         if (not _SAME($content, $data)) {
82 0           return _UPDATE($doc, $data);
83             }
84             }
85             }
86 0           return 0;
87             }
88              
89             sub _UPDATE {
90 0     0     my ($doc, $data, $newAttach) = @_;
91 0           $doc->attachments($newAttach);
92 0           $doc->data($data);
93 0           $doc->update();
94 0           return 2;
95             }
96              
97             sub addDesignDocUnlessExistsOrSame {
98 0     0 1   my $self = shift;
99 0           my $id = shift;
100 0           my $data = shift;
101            
102 0           my $db = $self->{db};
103 0 0         if (not $db->designDocExists($id)) {
104 0           $db->newDesignDoc($id, undef, $data)->create();
105 0           return 1;
106             }
107             else {
108 0           my $dd = $db->newDesignDoc($id)->retrieve();
109 0 0         if (not _SAME($dd->data, $data)) {
110 0           $dd->data($data)->update();
111 0           return 2;
112             }
113 0           return 0;
114             }
115             }
116              
117             sub getFile {
118 0     0 1   my $self = shift;
119 0           my $file = shift;
120            
121 0           $file = File::Spec->rel2abs(
122             $file,
123             File::Spec->rel2abs(
124             File::Spec->catpath( (File::Spec->splitpath($0))[0,1], '' )
125             )
126             );
127 0 0         open my $F, "<", $file or die "Can't open file: $file";
128 0           my $content = do { local $/ = undef; <$F> };
  0            
  0            
129 0           close $F;
130 0           return CouchDB::Client::Doc->toBase64($content);
131             }
132              
133             1;
134              
135             =pod
136              
137             =head1 NAME
138              
139             CouchDB::Deploy::Process - The default processor for deploying to CouchDB
140              
141             =head1 SYNOPSIS
142              
143             use CouchDB::Deploy;
144             ...
145              
146             =head1 DESCRIPTION
147              
148             This module does the actual dirty job of deploying to CouchDB. Other backends could
149             replace it (though that's not supported yet) and it can be used by other frontends.
150              
151             =head1 METHODS
152              
153             =over 8
154              
155             =item new $SERVER
156              
157             Constructor. Expects to be passed the server to which to deploy.
158              
159             =item createDBUnlessExists $NAME
160              
161             Creates the DB with the given name, or skips it if it already exists. Returns true
162             if it did do something.
163              
164             =item addDocumentUnlessExistsOrSame $ID, $DATA?, $ATTACH?
165              
166             Creates the document with the given ID and optional data and attachments. If the
167             document exists it will do its best to find out if the version in the database is
168             the same as the current one (including attachments). If it is the same it will be
169             skipped, otherwise it will be updated. On creation it returns 1, on update 2, and
170             if nothing was done 0.
171              
172             =item addDesignDocUnlessExistsOrSame $ID, $DATA
173              
174             Creates the design doc with the given ID and data. On creation it returns 1,
175             on update 2, and if nothing was done 0.
176              
177             =item getFile $PATH
178              
179             Returns the content of the file in a form suitable for usage in CouchDB attachments.
180             Dies if it can't find the file.
181              
182             =back
183              
184             =head1 AUTHOR
185              
186             Robin Berjon,
187              
188             =head1 BUGS
189              
190             Please report any bugs or feature requests to bug-couchdb-deploy at rt.cpan.org, or through the
191             web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CouchDb-Deploy.
192              
193             =head1 COPYRIGHT & LICENSE
194              
195             Copyright 2008 Robin Berjon, all rights reserved.
196              
197             This library is free software; you can redistribute it and/or modify it under the same terms as
198             Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may
199             have available.
200              
201             =cut
202