#include "config.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <locale.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <apt-pkg/configuration.h>
#include "langupdate.h"
#include "aptcache.h"
| #define | GNU_WARRANTY |
| #define | DPKG_II "^Package: (.*)$" |
| #define | GREX_EMPTY GRegexMatchFlags(0) |
| #define | DEBUG "" |
| debug handling | |
| #define | APTCONFIGSTR |
| Configuration string for apt. | |
| static guint | c = 0 |
| static const gchar * | sourceslist = "/var/lib/langupdate/sources.list" |
| static GList * | installed = NULL |
| static GList * | targets = NULL |
| static gchar * | suite_codename = NULL |
| static gchar * | user_suite = NULL |
| static gboolean | verbose = false |
| static gboolean | dry_run = false |
| static gboolean | show_version = false |
| static GOptionEntry | entries [] |
| gchar * | lu_get_aptstring (void) |
| Collate the various apt options into a string. | |
| static void | output (gpointer value, gpointer data) |
| static gchar * | parse_installed (const gchar *pkg, const gchar *locale) |
| Parses list of all installed packages. | |
| static gboolean | append_sourceslist (const gchar *lang) |
| write the sources list | |
| static void | lu_check_allowed_suites (gchar *user_suite) |
| checks the user specified suite against the allowed list | |
| gint | main (gint argc, gchar *argv[]) |
| Read the apt-cache to know what is available. then compare dpkg_list with apt_list. |
| #define APTCONFIGSTR |
Value:
"-o APT::Get::List-Cleanup=off " \ "-o Apt::Install-Recommends=false " \ "-o Dir=/var/lib/langupdate " \ "-o Dir::Etc=/var/lib/langupdate " \ "-o Dir::Etc::SourceList=sources.list " \ "-o Dir::State::Status=/var/lib/langupdate/status "
Provides the main mechanism to separate the tdeb cache from the apt cache.
| #define DEBUG "" |
debug handling
In theory, apt should not care about the architecture because the translations are Architecture: all. In practice, it appears that apt is not expecting an entire repository of architecture-independent packages. Emdebian only supports prebuilt target packages for arm (not armel or armeb) so apt will only find cache data if set to look for arm packages. Hence, if langupdate is being built on a different architecture, the langupdate cache needs to force apt to look for arm packages or the langupdate cache is likely to be empty.
This only arises during development and debugging. Once built for arm, langupdate does not need to pass the Apt::Architecture option.
FOREIGN is defined with a test in ./configure - update the test there if Emdebian gains support for other prebuilt target package architectures.
| #define DPKG_II "^Package: (.*)$" |
| #define GNU_WARRANTY |
Value:
"Copyright (C) 2007 Neil Williams <codehelp@debian.org>\n" \ "This is free software; see the source for copying conditions. There is NO\n" \ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
| #define GREX_EMPTY GRegexMatchFlags(0) |
| static gboolean append_sourceslist | ( | const gchar * | lang | ) | [static] |
write the sources list
00207 { 00208 FILE * fout = NULL; 00209 00210 fout = fopen (sourceslist, "a"); 00211 if (!fout) 00212 { 00213 g_warning (_("failed to create sources list: '%s'"), sourceslist); 00214 return false; 00215 } 00216 fprintf (fout, "deb http://buildd.emdebian.org/locale/ %s %s\n", suite_codename, lang); 00217 fclose (fout); 00218 return true;
| static void lu_check_allowed_suites | ( | gchar * | user_suite | ) | [static] |
checks the user specified suite against the allowed list
Sets the user specified suite if supported, otherwise sets the langupdate default (unstable).
00229 { 00230 gchar * allowed, * match; 00231 00232 match = NULL; 00233 /* Translators: used with the --suite option to confirm 00234 the suite codename entered by the user. */ 00235 g_print ("%s: %s %s\n", PACKAGE, _("checking Emdebian support for: "), user_suite); 00236 allowed = g_strdup("unstable sid testing lenny stable"); 00237 match = g_strrstr_len (allowed, strlen(allowed), user_suite); 00238 if (match) 00239 suite_codename = g_strdup(user_suite); 00240 else 00241 { 00242 g_warning (_("Suite '%s' is not supported by Emdebian."), user_suite); 00243 g_print ("\n%s: %s", PACKAGE, _("Using the default suite: unstable.\n")); 00244 suite_codename = g_strdup("unstable"); 00245 } g_free (user_suite); 00246 g_free (allowed);
| gchar* lu_get_aptstring | ( | void | ) |
Collate the various apt options into a string.
return the configuration options for apt
Depending on various settings, the apt configuration list needs to be adjusted so it cannot be completely defined as a macro. This function adds the customisations, creates a newly allocated string and returns it. The caller is responsible for freeing the string.
Also sets the langupdate cache data to the same configuration if this has not been done already.
00120 { 00121 return g_strconcat (DEBUG, APTCONFIGSTR, "-o Dir::State=", 00122 suite_codename, " -o Dir::Cache=", suite_codename, NULL);
| gint main | ( | gint | argc, | |
| gchar * | argv[] | |||
| ) |
Read the apt-cache to know what is available. then compare dpkg_list with apt_list.
00254 { 00255 GError * em_gerr; 00256 gchar * dpkg, *code; 00257 const gchar * const * locale_v; 00258 GList * dpkg_list, * p, *choices, *locales; 00259 GHashTable * tbl; 00260 gchar ** status_list; 00261 guint mcount, c, l; 00262 gint hdl; 00263 GOptionContext *context; 00264 00265 em_gerr = NULL; 00266 locales = dpkg_list = choices = NULL; 00267 tbl = g_hash_table_new (g_str_hash, g_str_equal); 00268 l = mcount = 0; 00269 #ifdef ENABLE_NLS 00270 setlocale (LC_ALL, ""); 00271 bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); 00272 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); 00273 textdomain (GETTEXT_PACKAGE); 00274 #endif 00275 context = g_option_context_new (_("- updates language support for emdebian")); 00276 g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); 00277 g_option_context_parse (context, &argc, &argv, &em_gerr); 00278 if (show_version) 00279 { 00280 g_print ("%s (%s).\n", PACKAGE, VERSION); 00281 g_print ("%s", GNU_WARRANTY); 00282 exit (0); 00283 } 00284 if (!user_suite) 00285 suite_codename = g_strdup("unstable"); 00286 else 00287 lu_check_allowed_suites(user_suite); 00288 #ifdef FOREIGN 00289 g_print ("%s: %s - %s\n", PACKAGE, HOST_OS, _("Foreign architecture, forcing a dry run.")); 00290 #else 00291 if (dry_run) 00292 g_print ("%s: %s\n", PACKAGE, _("Dry run, just showing cache data for installable packages.")); 00293 #endif 00294 locale_v = g_get_language_names (); 00295 if (!locale_v) 00296 return 0; 00297 while (strcmp (locale_v[l], "C") != 0) 00298 { 00299 code = g_ascii_strdown (locale_v[l], -1); 00300 if (!g_strrstr(code, ".")) 00301 { 00302 gchar * root; 00303 GRegex * patt; 00304 00305 em_gerr = NULL; 00306 patt = g_regex_new ("_", G_REGEX_OPTIMIZE, GREX_EMPTY, &em_gerr); 00307 if (em_gerr) 00308 { 00309 g_warning (em_gerr->message); 00310 g_clear_error (&em_gerr); 00311 } 00312 em_gerr = NULL; 00313 code = g_regex_replace (patt, code, -1, 0, "-", GREX_EMPTY, &em_gerr); 00314 if (em_gerr) 00315 { 00316 g_warning (em_gerr->message); 00317 g_clear_error (&em_gerr); 00318 } 00319 locales = g_list_append (locales, code); 00320 // need to get the root lang only here 00321 root = g_strndup(code, 2); 00322 if (!g_hash_table_lookup(tbl, root)) 00323 { 00324 if (!append_sourceslist (root)) 00325 return -1; 00326 g_hash_table_insert (tbl, root, code); 00327 } 00328 } 00329 else 00330 g_free (code); 00331 l++; 00332 } 00333 g_return_val_if_fail (apt_init (sourceslist, suite_codename, verbose), -1); 00334 if (!g_file_get_contents (DPKG_FILE, &dpkg, NULL, &em_gerr)) 00335 { 00336 g_critical (em_gerr->message); 00337 g_message (_("Unable to open the dpkg status file.")); 00338 g_clear_error (&em_gerr); 00339 return -1; 00340 } 00341 status_list = g_strsplit (dpkg, "\n", -1); 00342 00343 for (mcount = 0; mcount <= g_strv_length(status_list); mcount++) 00344 { 00345 gchar * pkg; 00346 if (!status_list[mcount]) 00347 continue; 00348 pkg = parse_installed (status_list[mcount], (gchar*)locales->data); 00349 if (pkg) 00350 dpkg_list = g_list_prepend (dpkg_list, pkg); 00351 } 00352 for (p = dpkg_list; p != NULL; p = p->next) 00353 { 00354 gchar * pkg = (gchar*)p->data; 00355 if (aptcache_lookup (pkg)) 00356 choices = g_list_prepend (choices, pkg); 00357 } 00358 c = g_list_length (choices); 00359 choices = g_list_sort (choices, check_pkg_name); 00360 c = g_list_length (choices); 00361 fprintf (stdout, ngettext("%d package can be installed\n\n", 00362 "%d packages can be installed\n\n", c), c); 00363 g_list_foreach (choices, output, NULL); 00364 g_hash_table_destroy (tbl); 00365 g_list_free (locales); 00366 g_list_free (choices); 00367 g_unlink ("/var/lib/langupdate/unstable/lists/lock"); 00368 g_unlink ("/var/lib/langupdate/lock"); 00369 #ifndef FOREIGN 00370 g_unlink (sourceslist); 00371 #endif 00372 return 0;
| static void output | ( | gpointer | value, | |
| gpointer | data | |||
| ) | [static] |
install each available package name
00131 { 00132 gchar * name, * hdl, * hdl_err, * config_str, * cmd, * func; 00133 gint err_status = 0; 00134 GError * gerr = NULL; 00135 00136 c++; 00137 config_str = lu_get_aptstring(); 00138 if (dry_run) 00139 { 00140 cmd = g_strdup("apt-cache"); 00141 func = g_strdup("show"); 00142 } 00143 else 00144 { 00145 cmd = g_strdup ("apt-get"); 00146 func = g_strdup("install -y"); 00147 } 00148 if ((value) && (strcmp ((gchar*)value, ""))) 00149 name = g_strdup_printf ( "%s %s %s %s", cmd, config_str, func, (gchar*)value); 00150 g_spawn_command_line_sync (name, &hdl, &hdl_err, &err_status, &gerr); 00151 if (gerr) 00152 { 00154 fprintf (stdout, _("apt returned an error:%s\n"), hdl_err); 00155 fprintf (stdout, _("status code:%d\n"), err_status); 00156 fprintf (stdout, "%s\n", gerr->message); 00157 return; 00158 } 00159 if (dry_run) 00160 fprintf (stdout, "%s\n", hdl);
| static gchar* parse_installed | ( | const gchar * | pkg, | |
| const gchar * | locale | |||
| ) | [static] |
Parses list of all installed packages.
Store a list of existing target packages by skipping those already installed.
00170 { 00171 GList * match; 00172 gchar ** pos; 00173 gchar * r, *target, * lang; 00174 00175 pos = g_strsplit (pkg, ": ", -1); 00176 if (!pos[0]) 00177 return NULL; 00178 r = NULL; 00179 match = NULL; 00180 lang = g_strconcat ("-", LOCALE_SUFFIX, "-", locale, NULL); 00181 if (0 == strcmp (pos[0], PACKAGE_CHK)) 00182 { 00183 r = g_strdup (pos[1]); 00184 if (g_str_has_suffix (r, lang)) 00185 { 00186 installed = g_list_prepend (installed, r); 00187 /* in case the target occurs later in the list */ 00188 targets = g_list_remove (targets, r); 00189 return NULL; 00190 } 00191 /* generate a target name. */ 00192 target = g_strconcat (r, lang, NULL); 00193 match = g_list_find_custom (installed, target, check_pkg_name); 00194 if (g_list_length (match) != 0) 00195 targets = g_list_prepend (targets, target); 00196 g_strfreev (pos); 00197 g_free (r); 00198 return target; 00199 } 00200 g_free (lang); 00201 return NULL;
guint c = 0 [static] |
gboolean dry_run = false [static] |
GOptionEntry entries[] [static] |
Initial value:
{
{ "dry-run", 'n', 0, G_OPTION_ARG_NONE, &dry_run, _("Only show the cache data, do not install"), 0 },
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, _("Be verbose"), NULL },
{ "suite", 0, 0, G_OPTION_ARG_STRING, &user_suite,
_("Specify the apt suite name [default unstable]"), _("codename") },
{ "version", 0, 0, G_OPTION_ARG_NONE, &show_version, _("Show version information "
"and exit."), 0},
{ NULL }
}
GList* installed = NULL [static] |
gboolean show_version = false [static] |
const gchar* sourceslist = "/var/lib/langupdate/sources.list" [static] |
gchar* suite_codename = NULL [static] |
GList* targets = NULL [static] |
gchar* user_suite = NULL [static] |
gboolean verbose = false [static] |
1.5.4