1 /* merge-points.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/mem/alloc-limits.h"
13 #include "hackerlab/char/str.h"
14 #include "hackerlab/vu/safe.h"
15 #include "tla/libfsutils/file-contents.h"
16 #include "tla/libarch/patch-logs.h"
17 #include "tla/libarch/namespace.h"
18 #include "tla/libarch/merge-points.h"
19 
20 
21 /* __STDC__ prototypes for static functions */
22 static void arch_add_merge_points (rel_table * out,
23                                    const t_uchar * level,
24                                    const t_uchar * log,
25                                    const t_uchar * prefix);
26 static t_uchar * arch_merge_points_prefix (const t_uchar * from_archive,
27                                            const t_uchar * from_spec);
28 
29 
30 
31 rel_table
arch_tree_merge_points(const t_uchar * tree_root,const t_uchar * into_archive,const t_uchar * into_spec,const t_uchar * from_archive,const t_uchar * from_spec)32 arch_tree_merge_points (const t_uchar * tree_root,
33                         const t_uchar * into_archive,
34                         const t_uchar * into_spec,
35                         const t_uchar * from_archive,
36                         const t_uchar * from_spec)
37 {
38   rel_table answer = rel_table_nil;
39   rel_table source_logs = rel_table_nil;
40   int x;
41   t_uchar * prefix = 0;
42 
43   if (arch_valid_package_name (into_spec, arch_no_archive, arch_req_patch_level, 0))
44     {
45       t_uchar * path = 0;
46       t_uchar * level = 0;
47 
48       path = arch_log_file (tree_root, into_archive, into_spec);
49       level = arch_parse_package_name (arch_ret_patch_level, 0, into_spec);
50 
51       rel_add_records (&source_logs, rel_make_record_2_taking (rel_make_field_str (into_spec), rel_make_field_str (path)), rel_record_null);
52 
53       lim_free (0, path);
54       lim_free (0, level);
55     }
56   else if (arch_valid_package_name (into_spec, arch_no_archive, arch_req_version, 0))
57     {
58       source_logs = arch_logs (tree_root, into_archive, into_spec, 0);
59     }
60   else
61     panic ("invalid into_spec argument to arch_tree_merge_points");
62 
63   prefix = arch_merge_points_prefix (from_archive, from_spec);
64 
65   for (x = 0; x < rel_n_records (source_logs); ++x)
66     {
67       t_uchar * log_text = 0;
68 
69       log_text = file_contents (rel_peek_str (source_logs, x, 1));
70 
71       arch_add_merge_points (&answer, rel_peek_str (source_logs, x, 0), log_text, prefix);
72 
73       lim_free (0, log_text);
74     }
75 
76 
77   rel_free_table (source_logs);
78   lim_free (0, prefix);
79 
80   return answer;
81 }
82 
83 
84 rel_table
arch_archive_merge_points(struct arch_archive * into_arch,const t_uchar * into_spec,const t_uchar * from_archive,const t_uchar * from_spec,int upto)85 arch_archive_merge_points (struct arch_archive * into_arch,
86                            const t_uchar * into_spec,
87                            const t_uchar * from_archive,
88                            const t_uchar * from_spec,
89                            int upto)
90 {
91   rel_table answer = rel_table_nil;
92   rel_table source_revisions = rel_table_nil;
93   int x;
94   t_uchar * prefix = 0;
95 
96   if (arch_valid_package_name (into_spec, arch_no_archive, arch_req_patch_level, 0))
97     {
98       if (!upto)
99         rel_add_records (&source_revisions, rel_singleton_record_taking (rel_make_field_str (into_spec)), rel_record_null);
100       else
101         {
102           t_uchar * into_version = 0;
103           rel_table all_source_revisions = rel_table_nil;
104 
105           into_version = arch_parse_package_name (arch_ret_package_version, 0, into_spec);
106           all_source_revisions = arch_archive_revisions (into_arch, into_version, 2);
107           for (x = 0; x < rel_n_records (all_source_revisions); ++x)
108             {
109               rel_add_records (&source_revisions, rel_copy_record (rel_peek_record (all_source_revisions, x)), rel_record_null);
110               if (!str_cmp (rel_peek_str (all_source_revisions, x, 0), into_spec))
111                 break;
112             }
113 
114           if (x == rel_n_records (all_source_revisions))
115             {
116               safe_printfmt (2, "arch: attempt to compute merge-points of non-existent revision\n  (%s\%s)\n", into_arch->name, into_spec);
117               exit (2);
118             }
119 
120           lim_free (0, into_version);
121           rel_free_table (all_source_revisions);
122         }
123     }
124   else if (arch_valid_package_name (into_spec, arch_no_archive, arch_req_version, 0))
125     {
126       source_revisions = arch_archive_revisions (into_arch, into_spec, 2);
127     }
128   else
129     panic ("invalid into_spec argument to arch_archive_merge_points");
130 
131 
132   prefix = arch_merge_points_prefix (from_archive, from_spec);
133 
134   for (x = 0; x < rel_n_records (source_revisions); ++x)
135     {
136       t_uchar * log_text = 0;
137       t_uchar * level = 0;
138 
139       log_text = arch_archive_log (into_arch, rel_peek_str (source_revisions, x, 0));
140       level = arch_parse_package_name (arch_ret_patch_level, 0, rel_peek_str (source_revisions, x, 0));
141 
142       arch_add_merge_points (&answer, level, log_text, prefix);
143 
144       lim_free (0, log_text);
145       lim_free (0, level);
146     }
147 
148 
149   rel_free_table (source_revisions);
150   lim_free (0, prefix);
151 
152   return answer;
153 }
154 
155 
156 rel_table
arch_new_in_version(const t_uchar * tree_root,const t_uchar * archive,const t_uchar * version)157 arch_new_in_version (const t_uchar * tree_root,
158                      const t_uchar * archive,
159                      const t_uchar * version)
160 {
161   rel_table merge_points = rel_table_nil;
162   rel_table all_logs = rel_table_nil;
163   rel_table answer = rel_table_nil;
164 
165   merge_points = arch_tree_merge_points (tree_root, archive, version, 0, 0);
166   all_logs = arch_all_logs (tree_root);
167 
168   rel_sort_table_by_field (0, merge_points, 1);
169   rel_sort_table_by_field (0, all_logs, 0);
170 
171   answer = rel_join (2, rel_join_output (2,0, -1), 1, 0, merge_points, all_logs);
172   arch_sort_table_by_name_field (0, answer, 0);
173 
174   rel_free_table (merge_points);
175   rel_free_table (all_logs);
176 
177   return answer;
178 }
179 
180 
181 
182 
183 static void
arch_add_merge_points(rel_table * out,const t_uchar * level,const t_uchar * log,const t_uchar * prefix)184 arch_add_merge_points (rel_table * out,
185                        const t_uchar * level,
186                        const t_uchar * log,
187                        const t_uchar * prefix)
188 {
189   assoc_table headers = 0;
190   const t_uchar * new_patches_header;
191   rel_table new_patches = rel_table_nil;
192   int x;
193 
194   arch_parse_log (0, &headers, 0, log);
195   new_patches_header = assoc_get_str_taking (headers, rel_make_field_str ("new-patches"));
196 
197   new_patches = rel_ws_split (new_patches_header);
198   arch_sort_table_by_name_field (0, new_patches, 0);
199   rel_uniq_by_field (&new_patches, 0);
200 
201   for (x = 0; x < rel_n_records (new_patches); ++x)
202     {
203       if (!str_cmp_prefix (prefix, rel_peek_str (new_patches, x, 0)))
204         rel_add_records (out, rel_make_record_2_taking (rel_make_field_str (level), rel_get_field (new_patches, x, 0)), rel_record_null);
205     }
206 
207   free_assoc_table (headers);
208   rel_free_table (new_patches);
209 }
210 
211 
212 static t_uchar *
arch_merge_points_prefix(const t_uchar * from_archive,const t_uchar * from_spec)213 arch_merge_points_prefix (const t_uchar * from_archive,
214                           const t_uchar * from_spec)
215 {
216   if (!from_archive)
217     return 0;
218   else if (arch_valid_package_name (from_spec, arch_no_archive, arch_req_patch_level, 0))
219     return arch_fully_qualify (from_archive, from_spec);
220   else
221     return str_alloc_cat_many (0, from_archive, "/", from_spec, "--", str_end);
222 }
223 
224 
225 
226 
227 
228 
229 /* tag: Tom Lord Tue May 27 18:04:17 2003 (merge-points.c)
230  */
231