thinko fixing the thinko :D one should test before commiting
[migration-tools.git] / emig
1 #!/usr/bin/perl -w
2 ###############################################################################
3 =pod
4
5 =head1 NAME
6
7 mig - git-like program for tracking and manipulating legacy data files for
8 migrations
9
10 =head1 SYNOPSIS
11
12 B<mig> <command> [argument] [...]
13
14 =head1 DESCRIPTION
15
16 B<mig> is used to track and manipulate CSV or CSV-like text files exported from
17 legacy systems for migration into Evergreen.  It can be a wrapper for some
18 other migration tools and tracks state using a PostgreSQL table in a given
19 migration schema.
20
21 It makes use of certain environment variables that may be set by the B<mig-env>
22 tool: PGHOST, PGPORT, PGUSER, PGDATABASE, MIGSCHEMA, and MIGWORKDIR
23
24 For most commands, if the current working directory falls outside of the
25 directory specified by MIGWORKDIR, then mig will assume that environment is
26 also incorrect and bail before doing any actual work.
27
28 ~/.pgpass should also be configured, as B<mig> will not prompt for a database
29 password.
30
31 Only the B<env> and B<help> commands work without the MIGSCHEMA environment
32 variable being set.
33
34 =head1 OVERVIEW
35
36 Using B<mig> should go something like this:
37
38 =over 15
39
40 =item mig env create m_foo # Sets up the environment
41
42 =item mig env use m_foo # Spawns a shell using the configured environment
43
44 =item mig init # creates the m_foo schema in the database if needed, and other tables
45
46 =item mig add patrons.tsv # tracks an incoming data file; repeat for additional files
47
48 =item mig bibstats foo.mrc # get summarized data about bibs and export barcode list
49
50 =item mig iconv patrons.tsv # convert it to UTF8, creating patrons.tsv.utf8
51
52 =item mig clean patrons.tsv # cleans the file, creating patrons.tsv.utf8.clean
53
54 =item mig link patrons.tsv actor_usr # makes the soon-to-be staging table a child of m_foo.actor_usr
55
56 =item mig convert patrons.tsv # creates a .sql file for staging the data
57
58 =item mig stage patrons.tsv # load said .sql file
59
60 =item mig mapper patrons.tsv # interactive tool for analyzing/mapping the staging table
61
62 =item mig analysis patrons.tsv # writes a summary .tsv file of mapped/flagged fields from the staging table
63
64 =item mig map patrons.tsv # apply configured mappings
65
66 =item mig write_prod patrons.tsv # creates a .sql file for pushing the staging data into production
67
68 =item mig reporter --analyst "Foo Fooer" --report_title "Foo Load Analysis" #creates an asciidoc report
69
70 =item mig gsheet --pull foo_tab_name OR --push foo_pg_table_name 
71
72 =item mig stagebibs --file foo.xml 
73
74 =back
75
76 =head1 COMMANDS
77
78 =over 15
79
80 =item B<help> [command]
81
82 Display this very same documentation, or specific documentation for one of the
83 commands listed here.
84
85 =item B<env> <create|use|show> <schema>
86
87 Invokes B<mig-env> with the same arguments.  I<mig-env> can set important
88 environment variables and spawn a shell with those variables, and it also does
89 some directory creation and symlinking.
90
91 =item B<init>
92
93 Create or re-create the PostgreSQL tracking table for the schema specified by
94 the MIGSCHEMA environment variable.  If needed, create the migration schema
95 itself and run migration_tools.init() and build() if the migration_tools schema
96 exists.
97
98 =item B<status> [file] [...]
99
100 Show status information for either the specified files or all tracked files if
101 no argument is given.
102
103 =item B<add> [--no-headers|--headers] <file> [file|--no-headers|--headers] [...]
104
105 Add the specified files to the migration tracker.  Until --no-headers is
106 specified, the tracker will assume the files have headers.
107
108 You can do crazy stuff like
109 B<mig add file1 --no-headers file2 file3 --headers file4>
110
111 =item B<remove> <file> [file] [...]
112
113 Remove the specified files from the migration tracker.
114
115 =item B<iconv> <file> [other arguments...]
116
117 Attempts to invoke B<iconv> on the specified tracked file, placing the output in
118 <file>.utf8
119
120 If given no other arguments, the invocation will lool like
121
122 =over 5
123
124 iconv -f ISO-8859-1 -t UTF-8 -o <file>.utf8 <file>
125
126 =back
127
128 otherwise, the arguments will be passed through like so
129
130 =over 5
131
132 iconv [other arguments...] -o <file>.utf8 <file>
133
134 =back
135
136 =item B<skip-iconv> <file>
137
138 If this is used instead of B<iconv>, then B<mig> will look for an existing
139 <file>.utf8 and use it instead of attempting to create one.
140
141 =item B<clean> <file> [other arguments...]
142
143 Attempts to invoke B<clean_csv> on the iconv-converted specified tracked file,
144 placing the output in <file>.utf8.clean
145
146 If given no other arguments, the invocation will lool like
147
148 =over 5
149
150 clean_csv --config scripts/clean.conf --fix --apply <--create-headers> <file>
151
152 =back
153
154 otherwise, the arguments will be passed through like so
155
156 =over 5
157
158 clean_csv [other arguments...] <file>
159
160 =back
161
162 =item B<skip-clean> <file>
163
164 If this is used instead of B<clean>, then B<mig> will look for an existing
165 <file>.utf8.clean and use it instead of attempting to create one.
166
167 =item B<link> <file> <parent table>
168
169 Associate the specified file with a parent table within the migration schema.
170
171 Linking multiple files to the same parent table is not allowed currently.
172
173 =item B<unlink> <file>
174
175 Removes any association between the specified file and a parent table within
176 the migration schema.
177
178 =item B<convert> <file>
179
180 Attempts to invoke B<csv2sql> on the .utf8.clean version of the specified
181 tracked file, creating either [file].utf8.clean.stage.sql or
182 <parent table>_stage.sql depending on whether the file has been linked to a
183 parent table within the migration schema or not.
184
185 If given no other arguments, the invocation will lool like
186
187 =over 5
188
189 csv2sql --config scripts/clean.conf --add-x-migrate --schema <MIGSCHEMA> [--parent <PARENT TABLE>] -o <[<file>.utf8.clean.stage.sql]|[parent_table_stage.sql]> <FILE>.utf8.clean
190
191 =back
192
193 otherwise, the arguments will be passed through like so
194
195 =over 5
196
197 csv2sql [other arguments...] -o <[<file>.utf8.clean.stage.sql]|[parent_table_stage.sql]> <file>.utf8.clean
198
199 =back
200
201 =item B<stage> <file> [other arguments...]
202
203 Load the SQL-converted version of the specified file into the migration schema.
204
205 Extra arguments are passed to the underlying call to psql
206
207 =item B<mapper> <file>
208
209 Interactive session for analyzing, flagging, and mapping legacy field data to
210 Evergreen fields.
211
212 Upon exit, generate either [file].clean.map.sql or <parent table>_map.sql. The
213 SQL generated will be UPDATE's for setting the Evergreen-specific columns for a
214 given file's staging tables, and TRUNCATE's and INSERT's for auxilary tables.
215 The files will have \include hooks for pulling in additional mapping files
216 (for example, end-user mappings for circ modifiers, etc.)
217
218 =item B<analysis> [file]
219
220 Writes a MIGSCHEMA.tsv file containing a break-down of mapped and flagged
221 fields from the specified file, or all staged files if no file is specified.
222
223 The main goal of the tsv file is to present end-user mappable data for circ
224 modifiers, shelving locations, patron profiles, etc.  We use spreadsheets for
225 this now but may move to a dedicated UI in the future.
226
227 =item B<map> [file]
228
229 Applies the mapping sql to the migration schema for the specified mapped file,
230 or for all mapped files if no file is specified.
231
232 =item B<write_prod> [file]
233
234 Generates <parent table>_prod.sql for the specified linked and mapped file, or
235 all such files if no file is specified.
236
237 =item B<sql> [arguments...]
238
239 A wrapper around the psql command.  At some point the plan is to shove mig-tracked variables into psql sessions.
240
241 =item B<reporter> --analyst "Analyst Name" --report_title "Report Title"
242
243 Generates an asciidoc file in the git working directory that can be converted to 
244 any appropriate format.  The analyst and report parameters are required.
245
246 Optional parameters are : 
247
248 --added_page_title and --added_page_file 
249
250 If one is used both must be.  The added page file can be plain text or asciidoc.  This
251 adds an extra arbitrary page of notes to the report.  Mig assumes the page file is in the mig git directory.
252
253 --tags
254
255 This will define a set of tags to use, if not set it will default to Circs, 
256 Holds, Actors, Bibs, Assets & Money. 
257
258 --debug
259
260 Gives more information about what is happening.
261
262 --reports_xml 
263
264 Allows you to override the default evergreen_staged_report.xml in the mig-xml folder.
265
266 =item B<gsheet> --pull or --push spreadsheet_tab
267
268 This uses the gsheet_tracked_table and gsheet_tracked column tables to map a Google Docs Spreadsheet tabs
269 with Postgres tables in the mig schema.  The spreadsheet is assumed to share the name as the mig schema. 
270 Tab names must be unique.  Each spreadsheet column needs a header that matches the column name in the matching 
271 table.  An oauth session key is also needed for your Google account and mig gsheet will look for it in the 
272 .mig directory.
273
274 =back
275
276 =cut
277
278 ###############################################################################
279
280 use strict;
281 use Switch;
282 use Env qw(
283     HOME PGHOST PGPORT PGUSER PGDATABASE MIGSCHEMA
284     MIGBASEWORKDIR MIGBASEGITDIR MIGGITDIR MIGWORKDIR
285 );
286 use Pod::Usage;
287 use FindBin;
288 my $mig_bin = "$FindBin::Bin/emig.d/bin/";
289 use lib "$FindBin::Bin/emig.d/bin";
290 use EMig;
291
292 pod2usage(-verbose => 2) if ! $ARGV[0];
293 switch($ARGV[0]) {
294     case "help" {
295         if (defined $ARGV[1]) {
296             my $cmd = $mig_bin . "mig-$ARGV[1]";
297             if (-e $cmd) {
298                 system( $mig_bin . "mig-$ARGV[1]", '--help' );
299             } else {
300                 pod2usage(-verbose => 2);
301             }
302         } else {
303             pod2usage(-verbose => 2);
304         }
305     }
306     case "map" {
307     }
308     case "load" {
309     }
310     case "wdir" {
311         print "$MIGWORKDIR\n";
312     }
313     case "gdir" {
314         print "$MIGBASEGITDIR\n";
315     }
316     case "sdir" {
317         print "$MIGGITDIR\n";
318     }
319     else {
320         standard_invocation(@ARGV);
321     }
322 }
323
324 sub standard_invocation {
325     my $cmd = shift;
326
327     if ($cmd ne 'env') { EMig::die_if_no_env_migschema(); }
328     if (-e $mig_bin . "mig-$cmd") {
329         system( $mig_bin . "mig-$cmd", @_ );
330     } else {
331         system( "mig-$cmd", @_ ) == 0 or die pod2usage(1);
332     }
333
334 }
335
336