1 /* commit.c:
2 *
3 ****************************************************************
4 * Copyright (C) 2003 Tom Lord
5 *
6 * See the file "COPYING" for further information about
7 * the copyright and warranty status of this work.
8 */
9
10
11 #include "hackerlab/bugs/panic.h"
12 #include "hackerlab/os/time.h"
13 #include "hackerlab/char/str.h"
14 #include "hackerlab/fs/file-names.h"
15 #include "hackerlab/vu/safe.h"
16 #include "tla/libdate/date-string.h"
17 #include "tla/libfsutils/string-files.h"
18 #include "tla/libfsutils/copy-file.h"
19 #include "tla/libfsutils/tmp-files.h"
20 #include "tla/libfsutils/rmrf.h"
21 #include "tla/libarch/diffs.h"
22 #include "tla/libarch/patch-logs.h"
23 #include "tla/libarch/invent.h"
24 #include "tla/libarch/my.h"
25 #include "tla/libarch/hooks.h"
26 #include "tla/libarch/namespace.h"
27 #include "tla/libarch/pristines.h"
28 #include "tla/libarch/project-tree.h"
29 #include "tla/libarch/make-changeset-files.h"
30 #include "tla/libarch/make-changeset.h"
31 #include "tla/libarch/changeset-report.h"
32 #include "tla/libarch/local-cache.h"
33 #include "tla/libarch/inv-ids.h"
34 #include "tla/libarch/changelogs.h"
35 #include "tla/libarch/apply-changeset.h"
36 #include "tla/libarch/inode-sig.h"
37 #include "tla/libarch/chatter.h"
38 #include "tla/libarch/commit.h"
39
40
41 /* __STDC__ prototypes for static functions */
42
43
44
45 static t_uchar * arch_prepare_commit_changeset (t_uchar ** changelog_loc_ret,
46 int chatter_fd,
47 t_uchar ** cooked_log_ret,
48 t_uchar * tree_root,
49 t_uchar * raw_log,
50 struct arch_archive * arch,
51 t_uchar * revision,
52 t_uchar * prev_level,
53 rel_table file_list,
54 int escape_classes);
55 static rel_table pick_non_control (rel_table table);
56 static rel_table pick_patch_logs (rel_table table);
57 static void arch_commit_mid_commit (t_uchar * tree_root, t_uchar * cooked_log);
58 static void arch_finish_commit (int chatter_fd,
59 t_uchar * tree_root,
60 t_uchar * archive,
61 t_uchar * prev_revision,
62 t_uchar * revision,
63 t_uchar * changeset,
64 t_uchar * changelog_loc,
65 int escape_classes,
66 int full_meta);
67 static void arch_commit_failed (t_uchar * tree_root, t_uchar * archive, t_uchar * revision, t_uchar * changeset);
68 static void commit_make_changeset_callback (void * vfd, const char * fmt, va_list ap);
69
70
71
72 void
arch_commit(int chatter_fd,struct arch_archive * arch,t_uchar * revision,t_uchar * tree_root,t_uchar * raw_log,rel_table file_list,int escape_classes)73 arch_commit (int chatter_fd,
74 struct arch_archive * arch,
75 t_uchar * revision,
76 t_uchar * tree_root,
77 t_uchar * raw_log,
78 rel_table file_list,
79 int escape_classes)
80 {
81 int full_meta;
82 t_uchar * errstr;
83 t_uchar * version = 0;
84 t_uchar * this_level = 0;
85 t_uchar * prev_revision = 0;
86 t_uchar * prev_level = 0;
87 t_uchar * changelog_loc = 0;
88 t_uchar * changeset_path = 0;
89 t_uchar * cooked_log = 0;
90 t_uchar * my_uid = 0;
91 t_uchar * txn_id = 0;
92 int error;
93
94 invariant (!!raw_log);
95
96 full_meta = arch_tree_has_meta_flag (tree_root);
97
98 version = arch_parse_package_name (arch_ret_package_version, 0, revision);
99 this_level = arch_parse_package_name (arch_ret_patch_level, 0, revision);
100 prev_revision = arch_previous_revision (arch, revision);
101 prev_level = arch_parse_package_name (arch_ret_patch_level, 0, prev_revision);
102
103 changeset_path = arch_prepare_commit_changeset (&changelog_loc, chatter_fd, &cooked_log, tree_root, raw_log, arch, revision, prev_level, file_list, escape_classes);
104
105 invariant (!!prev_level);
106
107 /* Check the error return code for the "precommit" hook and exit if non-zero.
108 */
109 error = arch_run_hook ("precommit", "ARCH_ARCHIVE", arch->name, "ARCH_REVISION", revision, "ARCH_TREE_ROOT", tree_root, (t_uchar*)0) ;
110 if (error)
111 {
112 safe_printfmt (2, "arch_commit: precommit hook function failed with error (%d)\n commit cancelled.\n", error);
113 exit (2);
114 }
115
116 my_uid = arch_my_id_uid ();
117 txn_id = arch_generate_txn_id ();
118
119 if (arch_archive_lock_revision (&errstr, arch, version, prev_level, my_uid, txn_id, this_level))
120 {
121 safe_printfmt (2, "arch_commit: unable to acquire revision lock (%s)\n tree: %s\n revision: %s/%s\n",
122 errstr, tree_root, arch->name, revision);
123 exit (2);
124 }
125
126 if (arch_archive_put_log (&errstr, arch, version, prev_level, my_uid, txn_id, cooked_log))
127 {
128 safe_printfmt (2, "arch_commit: unable to send log message to archive (%s)\n tree: %s\n revision: %s/%s\n",
129 errstr, tree_root, arch->name, version);
130 exit (2);
131 }
132
133 if (arch_archive_put_changeset (&errstr, arch, version, prev_level, my_uid, txn_id, this_level, changeset_path))
134 {
135 safe_printfmt (2, "arch_commit: unable to send changeset to archive (%s)\n tree: %s\n revision: %s/%s\n",
136 errstr, tree_root, arch->name, revision);
137 exit (2);
138 }
139
140 if (arch_revision_ready (&errstr, arch, version, prev_level, my_uid, txn_id, this_level))
141 {
142 safe_printfmt (2, "arch_commit: error sending revision to archive (%s)\n tree: %s\n revision: %s/%s\n",
143 errstr, tree_root, arch->name, revision);
144 exit (2);
145 }
146
147
148 arch_commit_mid_commit (tree_root, cooked_log);
149
150 if (arch_archive_finish_revision (&errstr, arch, version, prev_level, my_uid, txn_id, this_level))
151 {
152 arch_commit_failed (tree_root, arch->name, version, changeset_path);
153 safe_printfmt (2, "arch_commit: unable to complete commit transaction (%s)\n tree: %s\n revision: %s/%s\n",
154 errstr, tree_root, arch->name, version);
155 exit (2);
156 }
157
158 arch_finish_commit (chatter_fd, tree_root, arch->name, prev_revision, revision, changeset_path, changelog_loc, escape_classes, full_meta);
159
160 if (rel_n_records (file_list) == 0)
161 arch_snap_inode_sig (tree_root, arch->name, revision);
162 else
163 {
164 arch_snap_inode_sig_files(tree_root, arch->name, prev_revision, revision, file_list);
165 }
166
167 arch_run_hook ("commit", "ARCH_ARCHIVE", arch->name, "ARCH_REVISION", revision, "ARCH_TREE_ROOT", tree_root, (t_uchar*)0);
168
169 lim_free (0, version);
170 lim_free (0, this_level);
171 lim_free (0, prev_revision);
172 lim_free (0, prev_level);
173 lim_free (0, changeset_path);
174 lim_free (0, cooked_log);
175 lim_free (0, changelog_loc);
176 lim_free (0, my_uid);
177 lim_free (0, txn_id);
178 }
179
180
181
182
183 static t_uchar *
arch_prepare_commit_changeset(t_uchar ** changelog_loc_ret,int chatter_fd,t_uchar ** cooked_log_ret,t_uchar * tree_root,t_uchar * raw_log,struct arch_archive * arch,t_uchar * revision,t_uchar * prev_level,rel_table file_list,int escape_classes)184 arch_prepare_commit_changeset (t_uchar ** changelog_loc_ret,
185 int chatter_fd,
186 t_uchar ** cooked_log_ret,
187 t_uchar * tree_root,
188 t_uchar * raw_log,
189 struct arch_archive * arch,
190 t_uchar * revision,
191 t_uchar * prev_level,
192 rel_table file_list,
193 int escape_classes)
194 {
195 t_uchar * archive = arch->name;
196 t_uchar * tmp_stem = 0;
197 t_uchar * tmp_path = 0;
198 t_uchar * changeset_basename = 0;
199 t_uchar * changeset_path = 0; /* return value */
200 t_uchar * version = 0;
201 t_uchar * level = 0;
202 t_uchar * prev_revision = 0;
203 t_uchar * prev_rev_path = 0;
204 struct arch_make_changeset_report make_report = {0, }; /* should have a chatter callback here */
205 t_uchar * changelog_id_suffix = 0;
206 t_uchar * changelog_x_id = 0;
207 t_uchar * changelog_i_id = 0;
208 t_uchar * changelog_id = 0;
209 t_uchar * changelog_orig_loc = 0;
210 t_uchar * changelog_mod_loc = 0;
211 struct arch_changeset_report csr = {rel_table_nil, };
212 int changelog_diffs_fd = -1;
213 int changelog_add_fd = -1;
214 t_uchar * new_log_id = 0;
215 t_uchar * new_log_loc = 0;
216 int new_log_fd = -1;
217 t_uchar * new_log_path = 0;
218 t_uchar * cooked_log = 0;
219 t_uchar * new_changelog_path = 0;
220
221
222
223 /****************************************************************
224 * double check that we were handed a valid log message, if any
225 */
226 invariant (arch_valid_log_file (raw_log));
227
228
229 /****************************************************************
230 * make a temp dir for the changeset
231 */
232 tmp_stem = str_alloc_cat_many (0, ",,commit.", revision, "--", archive, str_end);
233 tmp_path = tmp_file_name (tree_root, tmp_stem);
234
235 rmrf_file (tmp_path);
236 safe_mkdir (tmp_path, 0777);
237
238 changeset_basename = str_alloc_cat (0, revision, ".patches");
239 changeset_path = file_name_in_vicinity (0, tmp_path, changeset_basename);
240
241
242 /****************************************************************
243 * Compute the raw changeset
244 *
245 * The changeset computed here does _not_ include an add of the new log
246 * message and does _not_ include updates to automatic changelogs.
247 */
248
249 version = arch_parse_package_name (arch_ret_package_version, 0, revision);
250 level = arch_parse_package_name (arch_ret_patch_level, 0, revision);
251 prev_revision = str_alloc_cat_many (0, version, "--", prev_level, str_end);
252 prev_rev_path = arch_find_or_make_local_copy (chatter_fd, tree_root, 0, arch, archive, prev_revision);
253
254 if (chatter_fd >= 0)
255 {
256 make_report.callback = commit_make_changeset_callback;
257 make_report.thunk = (void *)(long)chatter_fd;
258 }
259
260 if (!rel_n_records (file_list))
261 {
262 assoc_table inode_shortcut = 0;
263
264 arch_read_inode_sig (0, &inode_shortcut, tree_root, archive, prev_revision);
265
266 arch_make_changeset (&make_report, prev_rev_path, tree_root, changeset_path, arch_unspecified_id_tagging, arch_inventory_unrecognized, rel_table_nil, inode_shortcut, 0, escape_classes);
267
268 free_assoc_table (inode_shortcut);
269 }
270 else
271 arch_make_files_changeset (&make_report, changeset_path, file_list, prev_rev_path, tree_root, arch_unspecified_id_tagging, arch_inventory_unrecognized, escape_classes);
272
273 /****************************************************************
274 * Look for a Changelog for the version we're committing to.
275 */
276
277 changelog_id_suffix = str_alloc_cat_many (0, "_automatic-ChangeLog--", archive, "/", version, str_end);
278 changelog_x_id = str_alloc_cat (0, "x", changelog_id_suffix);
279 changelog_i_id = str_alloc_cat (0, "i", changelog_id_suffix);
280
281 {
282 const t_uchar * tmp;
283
284 tmp = assoc_get_str_taking (make_report.mod_file_loc_of, rel_make_field_str (changelog_x_id));
285 if (tmp)
286 {
287 changelog_mod_loc = str_save (0, tmp);
288 changelog_id = str_save (0, changelog_x_id);
289 }
290 else
291 {
292 const t_uchar * tmp;
293
294 tmp = assoc_get_str_taking (make_report.mod_file_loc_of, rel_make_field_str (changelog_i_id));
295 if (tmp)
296 {
297 changelog_mod_loc = str_save (0, tmp);
298 changelog_id = str_save (0, changelog_i_id);
299 }
300 else
301 {
302 changelog_mod_loc = 0;
303 changelog_id = 0;
304 }
305 }
306 }
307
308 if (changelog_mod_loc)
309 {
310 if (changelog_loc_ret)
311 {
312 *changelog_loc_ret = str_save (0, changelog_mod_loc);
313 }
314
315 {
316 const t_uchar * tmp;
317
318 tmp = assoc_get_str_taking (make_report.orig_file_loc_of, rel_make_field_str (changelog_id));
319 if (tmp)
320 changelog_orig_loc = str_save (0, tmp);
321 else
322 changelog_orig_loc = 0;
323 }
324 }
325
326 /* post-condition:
327 *
328 * changelog_id, changelog_mod_loc: 0 if no MOD tree changelog
329 * set if there is a changelog
330 *
331 * changelog_orig_loc: 0 if no MOD or no ORIG changelog, set if both
332 */
333
334
335 /****************************************************************
336 * Get a report about this changeset
337 */
338
339 arch_evaluate_changeset (&csr, changeset_path);
340
341
342 /****************************************************************
343 * Update the changeset indexes to reflect the patch log and changelog
344 *
345 * The changelog for this version, if any, is going to change
346 * as a result of the new patch log for this commit.
347 * Usually (though we don't count on it) it didn't change between
348 * pristine and project tree.
349 *
350 * So, we have to touch up the changeset to reflect a diff to that
351 * changelog. At this stage, only the file and dir indexes are
352 * modified to reflect that (we haven't generated the new log entry
353 * yet, so we can't produce the actual changelog diffs).
354 *
355 * Also, we know we're adding a new patch log, so the indexes should
356 * reflect that, too.
357 *
358 * The reason to touch up the indexes early is that the patch log
359 * is derived, in part, from those indexes.
360 */
361
362 if (changelog_mod_loc && changelog_orig_loc)
363 {
364 changelog_diffs_fd = arch_changeset_add_diffs (&csr, &make_report, changeset_path, changelog_orig_loc, changelog_mod_loc, changelog_id);
365 }
366 else if (changelog_mod_loc)
367 {
368 changelog_add_fd = arch_changeset_add_file (&new_changelog_path, &csr, &make_report, changeset_path, changelog_mod_loc, changelog_id);
369 }
370
371 new_log_loc = arch_log_file (".", archive, revision);
372 new_log_id = arch_log_file_id (archive, revision);
373 new_log_fd = arch_changeset_add_file (&new_log_path, &csr, &make_report, changeset_path, new_log_loc, new_log_id);
374
375 arch_changeset_rewrite_indexes (changeset_path, &csr);
376
377
378 /****************************************************************
379 * Generate the Cooked Log Entry
380 */
381 {
382 t_uchar * my_id = 0;
383 time_t now;
384 t_uchar * std_date = 0;
385 t_uchar * human_date = 0;
386 int log_fd;
387
388 my_id = arch_my_id ();
389 now = time (0);
390 std_date = standard_date (now);
391 human_date = pretty_date (now);
392
393 log_fd = make_output_to_string_fd ();
394
395 safe_printfmt (log_fd, "Revision: %s\n", revision);
396 safe_printfmt (log_fd, "Archive: %s\n", archive);
397 safe_printfmt (log_fd, "Creator: %s\n", my_id);
398 safe_printfmt (log_fd, "Date: %s\n", human_date);
399 safe_printfmt (log_fd, "Standard-date: %s\n", std_date);
400
401 /********************************
402 * automatic headers for various file and patch lists
403 */
404
405 {
406 rel_table new_files = rel_table_nil;
407 rel_table removed_files = rel_table_nil;
408 rel_table new_directories = rel_table_nil;
409 rel_table removed_directories = rel_table_nil;
410 rel_table modified_files = rel_table_nil;
411 rel_table new_patches = rel_table_nil;
412 rel_table removed_patches = rel_table_nil;
413
414 new_files = pick_non_control (csr.added_files);
415 rel_append_x (&new_files, csr.added_symlinks);
416 rel_sort_table_by_field (0, new_files, 0);
417
418 removed_files = pick_non_control (csr.removed_files);
419 rel_append_x (&removed_files, csr.removed_symlinks);
420 rel_sort_table_by_field (0, removed_files, 0);
421
422 new_directories = pick_non_control (csr.added_dirs);
423 removed_directories = pick_non_control (csr.removed_dirs);
424
425 modified_files = rel_copy_table (csr.patched_regular_files);
426 rel_append_x (&modified_files, csr.patched_symlinks);
427 rel_append_x (&modified_files, csr.patched_binaries);
428 rel_append_x (&modified_files, csr.file_metadata_changed);
429 rel_append_x (&modified_files, csr.symlink_to_file);
430 rel_append_x (&modified_files, csr.file_to_symlink);
431 rel_sort_table_by_field (0, modified_files, 0);
432 rel_uniq_by_field (&modified_files, 0);
433
434 new_patches = pick_patch_logs (csr.added_files);
435 removed_patches = pick_patch_logs (csr.removed_files);
436
437 arch_print_log_list_header (log_fd, "New-files", new_files, 0);
438 arch_print_log_list_header (log_fd, "New-directories", new_directories, 0);
439 arch_print_log_list_header (log_fd, "Removed-files", removed_files, 0);
440 arch_print_log_list_header (log_fd, "Removed-directories", removed_directories, 0);
441 arch_print_log_pairs_header (log_fd, "Renamed-files", csr.renamed_files, 0, 1);
442 arch_print_log_pairs_header (log_fd, "Renamed-directories", csr.renamed_dirs, 0, 1);
443 arch_print_log_list_header (log_fd, "Modified-files", modified_files, 0);
444 arch_print_log_list_header (log_fd, "Modified-directories", csr.dir_metadata_changed, 0);
445 arch_print_log_list_header (log_fd, "New-patches", new_patches, 0);
446 arch_print_log_list_header (log_fd, "Removed-patches", removed_patches, 0);
447
448 rel_free_table (new_files);
449 rel_free_table (removed_files);
450 rel_free_table (new_directories);
451 rel_free_table (removed_directories);
452 rel_free_table (modified_files);
453 rel_free_table (new_patches);
454 rel_free_table (removed_patches);
455 }
456
457
458 /********************************
459 * copy the user headers, and copy or generate the log body
460 */
461 {
462 t_uchar * eoh = raw_log;
463
464 while (1)
465 {
466 eoh = str_chr_index (eoh, '\n');
467 if (!eoh || (eoh[1] == '\n') || (!eoh[1]))
468 break;
469 else
470 ++eoh;
471 }
472
473 if (eoh)
474 {
475 eoh = eoh + 1;
476 safe_printfmt (log_fd, "%.*s", (int)(eoh - raw_log), raw_log);
477 }
478
479 if (eoh && *eoh)
480 {
481 safe_printfmt (log_fd, "%s", eoh);
482 }
483 else
484 {
485 safe_printfmt (log_fd, "\n\n");
486 }
487 }
488
489 /********************************
490 * oh... did i mention we were writing
491 * the log to a string?
492 */
493 cooked_log = string_fd_close (log_fd);
494
495 lim_free (0, my_id);
496 lim_free (0, std_date);
497 lim_free (0, human_date);
498 }
499
500 /****************************************************************
501 * Write the log into the changeset
502 */
503 safe_printfmt (new_log_fd, "%s", cooked_log);
504 safe_close (new_log_fd);
505
506
507 /****************************************************************
508 * Give a copy of the log to the caller.
509 */
510 if (cooked_log_ret)
511 *cooked_log_ret = str_save (0, cooked_log);
512
513
514 /****************************************************************
515 * Generate the new changelog.
516 */
517
518 if (changelog_add_fd > 0)
519 {
520 invariant (changelog_add_fd >= 0);
521 invariant (changelog_diffs_fd < 0);
522
523 arch_generate_changelog (changelog_add_fd, tree_root, 0, 0, level, new_log_path, archive, version);
524 /* new_changelog_path already set. */
525 safe_close (changelog_add_fd);
526 }
527 else if (changelog_diffs_fd > 0)
528 {
529 int fd = -1;
530 t_uchar * changelog_orig_path = 0;
531
532 new_changelog_path = file_name_in_vicinity (0, changeset_path, ",,changelog");
533 fd = safe_open (new_changelog_path, O_WRONLY | O_CREAT | O_EXCL, 0444);
534 arch_generate_changelog (fd, tree_root, 0, 0, level, new_log_path, archive, version);
535 safe_close (fd);
536
537 changelog_orig_path = file_name_in_vicinity (0, prev_rev_path, changelog_orig_loc);
538
539 invariant (changelog_diffs_fd >= 0);
540 invariant (changelog_add_fd < 0);
541
542 arch_invoke_diff (changelog_diffs_fd, changelog_orig_path, changelog_orig_loc, new_changelog_path, changelog_mod_loc, 0, 0);
543
544 safe_close (changelog_diffs_fd);
545
546 rmrf_file (new_changelog_path);
547
548 lim_free (0, changelog_orig_path);
549 }
550
551 lim_free (0, tmp_stem);
552 lim_free (0, tmp_path);
553 lim_free (0, changeset_basename);
554 lim_free (0, version);
555 lim_free (0, level);
556 lim_free (0, prev_revision);
557 lim_free (0, prev_rev_path);
558 arch_free_make_changeset_report_data (&make_report);
559 lim_free (0, changelog_id_suffix);
560 lim_free (0, changelog_x_id);
561 lim_free (0, changelog_i_id);
562 lim_free (0, changelog_id);
563 lim_free (0, changelog_orig_loc);
564 lim_free (0, changelog_mod_loc);
565 arch_free_changeset_report_data (&csr);
566 lim_free (0, new_log_id);
567 lim_free (0, new_log_loc);
568 lim_free (0, new_log_path);
569 lim_free (0, cooked_log);
570 lim_free (0, new_changelog_path);
571
572 /****************************************************************
573 * Give the user the path to the pristine tree for base-0.
574 * It's up tot he caller to stash this in the archive.
575 */
576 return changeset_path;
577 }
578
579
580 static rel_table
pick_non_control(rel_table table)581 pick_non_control (rel_table table)
582 {
583 int x;
584 rel_table answer = rel_table_nil;
585
586 for (x = 0; x < rel_n_records (table); ++x)
587 {
588 const t_uchar * id;
589
590 id = rel_peek_str (table, x, 1);
591
592 if (str_cmp_prefix ("A_", id))
593 rel_add_records (&answer, rel_copy_record (rel_peek_record (table, x)), rel_record_null);
594 }
595
596 return answer;
597 }
598
599
600 static rel_table
pick_patch_logs(rel_table table)601 pick_patch_logs (rel_table table)
602 {
603 int x;
604 rel_table answer = rel_table_nil;
605
606 for (x = 0; x < rel_n_records (table); ++x)
607 {
608 t_uchar * f = 0;
609 t_uchar * t = 0;
610 t_uchar * d = 0;
611 t_uchar * level = 0;
612 t_uchar * archive = 0;
613 t_uchar * version = 0;
614 t_uchar * revision = 0;
615 t_uchar * fqrev = 0;
616
617 f = str_save (0, rel_peek_str (table, x, 0));
618 t = file_name_tail (0, f);
619 d = file_name_directory_file (0, f);
620
621 if (arch_valid_patch_level_name (t))
622 {
623 level = str_save (0, t);
624
625 lim_free (0, f);
626 f = d;
627 t = file_name_tail (0, f);
628 d = file_name_directory_file (0, f);
629
630 if (!str_cmp ("patch-log", t))
631 {
632 lim_free (0, f);
633 f = d;
634 t = file_name_tail (0, f);
635 d = file_name_directory_file (0, f);
636
637 if (arch_valid_archive_name (t))
638 {
639 archive = str_save (0, t);
640
641 lim_free (0, f);
642 f = d;
643 t = file_name_tail (0, f);
644 d = file_name_directory_file (0, f);
645
646 if (arch_valid_package_name (t, arch_no_archive, arch_req_version, 0))
647 {
648 version = str_save (0, t);
649
650 lim_free (0, f);
651 f = d;
652 t = file_name_tail (0, f);
653 d = file_name_directory_file (0, f);
654
655 if (arch_valid_package_name (t, arch_no_archive, arch_req_package, 0))
656 {
657 lim_free (0, f);
658 f = d;
659 t = file_name_tail (0, f);
660 d = file_name_directory_file (0, f);
661
662 if (arch_valid_package_name (t, arch_no_archive, arch_req_category, 0))
663 {
664 if (!str_cmp ("./{arch}", d))
665 {
666 revision = str_alloc_cat_many (0, version, "--", level, str_end);
667 fqrev = arch_fully_qualify (archive, revision);
668 rel_add_records (&answer,
669 rel_make_record_3_taking (rel_make_field_str (fqrev),
670 rel_get_field (table, x, 1),
671 rel_get_field (table, x, 2)),
672 rel_record_null);
673 }
674 }
675 }
676
677 }
678 }
679 }
680 lim_free (0, f);
681 lim_free (0, t);
682 lim_free (0, d);
683 lim_free (0, level);
684 lim_free (0, archive);
685 lim_free (0, version);
686 lim_free (0, revision);
687 lim_free (0, fqrev);
688 }
689 }
690
691 arch_sort_table_by_name_field (0, answer, 0);
692
693 return answer;
694 }
695
696
697 static void
arch_commit_mid_commit(t_uchar * tree_root,t_uchar * cooked_log)698 arch_commit_mid_commit (t_uchar * tree_root, t_uchar * cooked_log)
699 {
700 arch_start_tree_commit (tree_root, cooked_log);
701 }
702
703
704 static void
arch_finish_commit(int chatter_fd,t_uchar * tree_root,t_uchar * archive,t_uchar * prev_revision,t_uchar * revision,t_uchar * changeset,t_uchar * changelog_loc,int escape_classes,int full_meta)705 arch_finish_commit (int chatter_fd,
706 t_uchar * tree_root,
707 t_uchar * archive,
708 t_uchar * prev_revision,
709 t_uchar * revision,
710 t_uchar * changeset,
711 t_uchar * changelog_loc,
712 int escape_classes,
713 int full_meta)
714 {
715 t_uchar * dir = 0;
716 t_uchar * dir_tail = 0;
717 t_uchar * recycled_pristine_src = 0;
718 t_uchar * recycled_pristine_tmp = 0;
719
720 dir = file_name_directory_file (0, changeset);
721 dir_tail = file_name_tail (0, dir);
722 invariant (!str_cmp_prefix (",,", dir_tail));
723
724 arch_finish_tree_commit (tree_root, archive, revision, changelog_loc, full_meta);
725
726 recycled_pristine_src = arch_find_pristine (0, tree_root, archive, prev_revision, arch_unlocked_pristine, arch_tree_pristine_search);
727 if (recycled_pristine_src)
728 {
729 t_uchar * inventory_path = 0;
730 struct arch_apply_changeset_report report = {0, };
731
732 arch_chatter (chatter_fd, "* update pristine tree (%s/%s => %s)\n", archive, prev_revision, revision);
733
734 recycled_pristine_tmp = tmp_file_name (dir, ",,pristine");
735 safe_rename (recycled_pristine_src, recycled_pristine_tmp);
736
737 inventory_path = file_name_in_vicinity (0, recycled_pristine_tmp, ",,index");
738 rmrf_file (inventory_path);
739
740 arch_apply_changeset (&report, changeset, recycled_pristine_tmp, arch_unspecified_id_tagging, arch_inventory_unrecognized, 0, 0, 0, 0, 0, escape_classes);
741 invariant (!arch_conflicts_occured (&report));
742
743 arch_install_pristine (tree_root, archive, revision, recycled_pristine_tmp);
744
745 lim_free (0, inventory_path);
746 }
747
748 rmrf_file (dir);
749
750 lim_free (0, dir);
751 lim_free (0, dir_tail);
752 lim_free (0, recycled_pristine_src);
753 lim_free (0, recycled_pristine_tmp);
754 }
755
756
757 static void
arch_commit_failed(t_uchar * tree_root,t_uchar * archive,t_uchar * revision,t_uchar * changeset)758 arch_commit_failed (t_uchar * tree_root, t_uchar * archive, t_uchar * revision, t_uchar * changeset)
759 {
760 t_uchar * dir = 0;
761 t_uchar * dir_tail = 0;
762
763 dir = file_name_directory_file (0, changeset);
764 dir_tail = file_name_tail (0, dir);
765 invariant (!str_cmp_prefix (",,", dir_tail));
766
767 arch_abort_tree_commit (tree_root, archive, revision);
768
769
770 rmrf_file (dir);
771
772 lim_free (0, dir);
773 lim_free (0, dir_tail);
774 }
775
776
777 static void
commit_make_changeset_callback(void * vfd,const char * fmt,va_list ap)778 commit_make_changeset_callback (void * vfd, const char * fmt, va_list ap)
779 {
780 int fd;
781
782 fd = (int)(t_ulong)vfd;
783 safe_printfmt_va_list (fd, fmt, ap);
784 safe_flush (1);
785 }
786
787
788
789
790
791
792 /* tag: Tom Lord Mon May 26 12:05:54 2003 (commit.c)
793 */
794