*/
#include <sys/types.h>
-#include <limits.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "repo.h"
#include "repo_write.h"
#include "common_write.h"
+#include "solvversion.h"
-#define LIBSOLV_TOOLVERSION "1.0"
-
-static Id verticals[] = {
- SOLVABLE_AUTHORS,
- SOLVABLE_DESCRIPTION,
- SOLVABLE_MESSAGEDEL,
- SOLVABLE_MESSAGEINS,
- SOLVABLE_EULA,
- SOLVABLE_DISKUSAGE,
- SOLVABLE_FILELIST,
- 0
-};
-
-static char *languagetags[] = {
- "solvable:summary:",
- "solvable:description:",
- "solvable:messageins:",
- "solvable:messagedel:",
- "solvable:eula:",
- 0
-};
-
-static int test_separate = 0;
-
-struct keyfilter_data {
- char **languages;
- int nlanguages;
- int haveaddedfileprovides;
- int haveexternal;
-};
+/* toolversion history
+ * 1.0: initial tool version
+ * 1.1: changed PRODUCT_ENDOFLIFE parsing
+ * 1.2: added UPDATE_COLLECTIONLIST to updateinfo
+*/
static int
-keyfilter_solv(Repo *data, Repokey *key, void *kfdata)
+keyfilter_solv(Repo *repo, Repokey *key, void *kfdata)
{
- struct keyfilter_data *kd = kfdata;
- int i;
- const char *keyname;
-
- if (test_separate && key->storage != KEY_STORAGE_SOLVABLE)
- return KEY_STORAGE_DROPPED;
- if (!kd->haveaddedfileprovides && key->name == REPOSITORY_ADDEDFILEPROVIDES)
+ if (key->name == SUSETAGS_SHARE_NAME || key->name == SUSETAGS_SHARE_EVR || key->name == SUSETAGS_SHARE_ARCH)
return KEY_STORAGE_DROPPED;
- if (!kd->haveexternal && key->name == REPOSITORY_EXTERNAL)
- return KEY_STORAGE_DROPPED;
- for (i = 0; verticals[i]; i++)
- if (key->name == verticals[i])
- return KEY_STORAGE_VERTICAL_OFFSET;
- keyname = id2str(data->pool, key->name);
- for (i = 0; languagetags[i] != 0; i++)
- if (!strncmp(keyname, languagetags[i], strlen(languagetags[i])))
- return KEY_STORAGE_VERTICAL_OFFSET;
- return KEY_STORAGE_INCORE;
-}
-
-static int
-keyfilter_attr(Repo *data, Repokey *key, void *kfdata)
-{
- int i;
- const char *keyname;
- if (key->storage == KEY_STORAGE_SOLVABLE)
- return KEY_STORAGE_DROPPED;
- /* those must only be in the main solv file */
- if (key->name == REPOSITORY_EXTERNAL || key->name == REPOSITORY_ADDEDFILEPROVIDES || key->name == REPOSITORY_TOOLVERSION)
- return KEY_STORAGE_DROPPED;
- for (i = 0; verticals[i]; i++)
- if (key->name == verticals[i])
- return KEY_STORAGE_VERTICAL_OFFSET;
- keyname = id2str(data->pool, key->name);
- for (i = 0; languagetags[i] != 0; i++)
- if (!strncmp(keyname, languagetags[i], strlen(languagetags[i])))
- return KEY_STORAGE_VERTICAL_OFFSET;
- return KEY_STORAGE_INCORE;
-}
-
-static int
-keyfilter_language(Repo *repo, Repokey *key, void *kfdata)
-{
- Pool *pool = repo->pool;
- const char *name, *p;
- char *lang = kfdata;
- int i;
-
- name = id2str(repo->pool, key->name);
- p = strrchr(name, ':');
- if (!p || strcmp(p + 1, lang) != 0)
- return KEY_STORAGE_DROPPED;
- for (i = 0; verticals[i]; i++)
- {
- const char *vname = id2str(pool, verticals[i]);
- if (!strncmp(name, vname, p - name) && vname[p - name] == 0)
- return KEY_STORAGE_VERTICAL_OFFSET;
- }
- return KEY_STORAGE_INCORE;
-}
-
-static int
-keyfilter_DU(Repo *repo, Repokey *key, void *kfdata)
-{
- int i;
- if (key->name != SOLVABLE_DISKUSAGE)
- return KEY_STORAGE_DROPPED;
- for (i = 0; verticals[i]; i++)
- if (key->name == verticals[i])
- return KEY_STORAGE_VERTICAL_OFFSET;
- return KEY_STORAGE_INCORE;
-}
-
-static int
-keyfilter_FL(Repo *repo, Repokey *key, void *kfdata)
-{
- int i;
- if (key->name != SOLVABLE_FILELIST)
- return KEY_STORAGE_DROPPED;
- for (i = 0; verticals[i]; i++)
- if (key->name == verticals[i])
- return KEY_STORAGE_VERTICAL_OFFSET;
- return KEY_STORAGE_INCORE;
-}
-
-static int
-keyfilter_other(Repo *repo, Repokey *key, void *kfdata)
-{
- const char *name, *p;
- struct keyfilter_data *kd = kfdata;
- int i;
-
- if (!kd->haveaddedfileprovides && key->name == REPOSITORY_ADDEDFILEPROVIDES)
- return KEY_STORAGE_DROPPED;
- if (!kd->haveexternal && key->name == REPOSITORY_EXTERNAL)
- return KEY_STORAGE_DROPPED;
-
- if (key->name == SOLVABLE_FILELIST || key->name == SOLVABLE_DISKUSAGE)
- return KEY_STORAGE_DROPPED;
-
- name = id2str(repo->pool, key->name);
- p = strrchr(name, ':');
- if (p)
- {
- for (i = 0; i < kd->nlanguages; i++)
- if (!strcmp(p + 1, kd->languages[i]))
- return KEY_STORAGE_DROPPED;
- }
- for (i = 0; verticals[i]; i++)
- if (key->name == verticals[i])
- return KEY_STORAGE_VERTICAL_OFFSET;
- return KEY_STORAGE_INCORE;
+ return repo_write_stdkeyfilter(repo, key, kfdata);
}
/*
- * Write <repo> to stdout
- * If <attrname> is given, write attributes to <attrname>
- * If <basename> is given, split attributes
+ * Write <repo> to fp
*/
-
-#define REPODATAFILE_BLOCK 15
-
-static void
-write_info(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Repodata *info, const char *location)
-{
- Id h, *keyarray = 0;
- int i;
-
- repo_write(repo, fp, keyfilter, kfdata, &keyarray);
- h = repodata_new_handle(info);
- if (keyarray)
- {
- for (i = 0; keyarray[i]; i++)
- repodata_add_idarray(info, h, REPOSITORY_KEYS, keyarray[i]);
- }
- sat_free(keyarray);
- repodata_set_str(info, h, REPOSITORY_LOCATION, location);
- repodata_add_flexarray(info, SOLVID_META, REPOSITORY_EXTERNAL, h);
-}
-
-int
-tool_write(Repo *repo, const char *basename, const char *attrname)
+void
+tool_write(Repo *repo, FILE *fp)
{
- Repodata *data;
- Repodata *info = 0;
- Repokey *key;
- char **languages = 0;
- int nlanguages = 0;
- int i, j, k, l;
- Id *addedfileprovides = 0;
- struct keyfilter_data kd;
+ Repodata *info;
+ Queue addedfileprovides;
+ Repowriter *writer;
- memset(&kd, 0, sizeof(kd));
- info = repo_add_repodata(repo, 0);
+ info = repo_add_repodata(repo, 0); /* add new repodata for our meta info */
repodata_set_str(info, SOLVID_META, REPOSITORY_TOOLVERSION, LIBSOLV_TOOLVERSION);
- pool_addfileprovides_ids(repo->pool, 0, &addedfileprovides);
- if (addedfileprovides && *addedfileprovides)
- {
- kd.haveaddedfileprovides = 1;
- for (i = 0; addedfileprovides[i]; i++)
- repodata_add_idarray(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, addedfileprovides[i]);
- }
- sat_free(addedfileprovides);
+ repodata_unset(info, SOLVID_META, REPOSITORY_EXTERNAL); /* do not propagate this */
+
+ queue_init(&addedfileprovides);
+ pool_addfileprovides_queue(repo->pool, &addedfileprovides, 0);
+ if (addedfileprovides.count)
+ repodata_set_idarray(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &addedfileprovides);
+ else
+ repodata_unset(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES);
+ queue_free(&addedfileprovides);
pool_freeidhashes(repo->pool); /* free some mem */
- if (basename)
+ repodata_internalize(info);
+ writer = repowriter_create(repo);
+ repowriter_set_keyfilter(writer, keyfilter_solv, 0);
+ if (repowriter_write(writer, fp) != 0)
{
- char fn[4096];
- FILE *fp;
- int has_DU = 0;
- int has_FL = 0;
-
- /* find languages and other info */
- for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
- {
- for (j = 1, key = data->keys + j; j < data->nkeys; j++, key++)
- {
- const char *keyname = id2str(repo->pool, key->name);
- if (key->name == SOLVABLE_DISKUSAGE)
- has_DU = 1;
- if (key->name == SOLVABLE_FILELIST)
- has_FL = 1;
- for (k = 0; languagetags[k] != 0; k++)
- if (!strncmp(keyname, languagetags[k], strlen(languagetags[k])))
- break;
- if (!languagetags[k])
- continue;
- l = strlen(languagetags[k]);
- if (strlen(keyname + l) > 5)
- continue;
- for (k = 0; k < nlanguages; k++)
- if (!strcmp(languages[k], keyname + l))
- break;
- if (k < nlanguages)
- continue;
- languages = sat_realloc2(languages, nlanguages + 1, sizeof(char *));
- languages[nlanguages++] = strdup(keyname + l);
- }
- }
- /* write language subfiles */
- for (i = 0; i < nlanguages; i++)
- {
- sprintf(fn, "%s.%s.solv", basename, languages[i]);
- if (!(fp = fopen(fn, "w")))
- {
- perror(fn);
- exit(1);
- }
- write_info(repo, fp, keyfilter_language, languages[i], info, fn);
- fclose(fp);
- kd.haveexternal = 1;
- }
- /* write DU subfile */
- if (has_DU)
- {
- sprintf(fn, "%s.DU.solv", basename);
- if (!(fp = fopen(fn, "w")))
- {
- perror(fn);
- exit(1);
- }
- write_info(repo, fp, keyfilter_DU, 0, info, fn);
- fclose(fp);
- kd.haveexternal = 1;
- }
- /* write filelist */
- if (has_FL)
- {
- sprintf(fn, "%s.FL.solv", basename);
- if (!(fp = fopen(fn, "w")))
- {
- perror(fn);
- exit(1);
- }
- write_info(repo, fp, keyfilter_FL, 0, info, fn);
- fclose(fp);
- kd.haveexternal = 1;
- }
- /* write everything else */
- sprintf(fn, "%s.solv", basename);
- if (!(fp = fopen(fn, "w")))
- {
- perror(fn);
- exit(1);
- }
- kd.languages = languages;
- kd.nlanguages = nlanguages;
- repodata_internalize(info);
- repo_write(repo, fp, keyfilter_other, &kd, 0);
- fclose(fp);
- for (i = 0; i < nlanguages; i++)
- free(languages[i]);
- sat_free(languages);
- repodata_free(info);
- return 0;
+ fprintf(stderr, "repo write failed: %s\n", pool_errstr(repo->pool));
+ exit(1);
}
- if (attrname)
+ if (fflush(fp))
{
- test_separate = 1;
- FILE *fp = fopen(attrname, "w");
- write_info(repo, fp, keyfilter_attr, 0, info, attrname);
- fclose(fp);
- kd.haveexternal = 1;
+ perror("fflush");
+ exit(1);
}
- repodata_internalize(info);
- repo_write(repo, stdout, keyfilter_solv, &kd, 0);
- repodata_free(info);
- return 0;
+ repowriter_free(writer);
+ repodata_free(info); /* delete meta info repodata again */
}