#include "repo.h"
#include "repo_write.h"
#include "common_write.h"
+#include "solvversion.h"
+
+/* toolversion history
+ * 1.0: initial tool version
+ * 1.1: changed PRODUCT_ENDOFLIFE parsing
+*/
static Id verticals[] = {
SOLVABLE_AUTHORS,
SOLVABLE_EULA,
SOLVABLE_DISKUSAGE,
SOLVABLE_FILELIST,
+ SOLVABLE_CHANGELOG_AUTHOR,
+ SOLVABLE_CHANGELOG_TEXT,
0
};
"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;
+};
+
static int
keyfilter_solv(Repo *data, 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)
+ 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 = pool_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;
}
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 = pool_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, *bname;
+ char *lang = kfdata;
int i;
- Id id;
- name = id2str(repo->pool, key->name);
+ name = pool_id2str(repo->pool, key->name);
p = strrchr(name, ':');
if (!p || strcmp(p + 1, lang) != 0)
return KEY_STORAGE_DROPPED;
- /* find base name id */
- bname = strdup(name);
- bname[p - name] = 0;
- id = str2id(repo->pool, bname, 1);
for (i = 0; verticals[i]; i++)
- if (id == verticals[i])
- return KEY_STORAGE_VERTICAL_OFFSET;
+ {
+ const char *vname = pool_id2str(pool, verticals[i]);
+ if (!strncmp(name, vname, p - name) && vname[p - name] == 0)
+ return KEY_STORAGE_VERTICAL_OFFSET;
+ }
return KEY_STORAGE_INCORE;
}
return KEY_STORAGE_INCORE;
}
-struct keyfilter_other_data {
- char **languages;
- int nlanguages;
-};
-
static int
keyfilter_other(Repo *repo, Repokey *key, void *kfdata)
{
const char *name, *p;
- struct keyfilter_other_data *kd = kfdata;
+ 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);
+ name = pool_id2str(repo->pool, key->name);
p = strrchr(name, ':');
if (p)
{
#define REPODATAFILE_BLOCK 15
-int
+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;
+ Queue keyq;
+
+ queue_init(&keyq);
+ if (repo_write_filtered(repo, fp, keyfilter, kfdata, &keyq) != 0)
+ {
+ fprintf(stderr, "repo_write failed\n");
+ exit(1);
+ }
+ h = repodata_new_handle(info);
+ if (keyq.count)
+ repodata_set_idarray(info, h, REPOSITORY_KEYS, &keyq);
+ queue_free(&keyq);
+ repodata_set_str(info, h, REPOSITORY_LOCATION, location);
+ repodata_add_flexarray(info, SOLVID_META, REPOSITORY_EXTERNAL, h);
+}
+
+void
tool_write(Repo *repo, const char *basename, const char *attrname)
{
Repodata *data;
+ Repodata *info = 0;
Repokey *key;
- Repodatafile *fileinfos = 0;
- int nfileinfos = 0;
char **languages = 0;
int nlanguages = 0;
int i, j, k, l;
+ struct keyfilter_data kd;
+ Queue addedfileprovides;
+
+ memset(&kd, 0, sizeof(kd));
+ info = repo_add_repodata(repo, 0);
+ repodata_set_str(info, SOLVID_META, REPOSITORY_TOOLVERSION, LIBSOLV_TOOLVERSION);
+ queue_init(&addedfileprovides);
+ pool_addfileprovides_queue(repo->pool, &addedfileprovides, 0);
+ if (addedfileprovides.count)
+ {
+ kd.haveaddedfileprovides = 1;
+ repodata_set_idarray(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &addedfileprovides);
+ }
+ queue_free(&addedfileprovides);
- fileinfos = sat_zextend(fileinfos, nfileinfos, 1, sizeof(Repodatafile), REPODATAFILE_BLOCK);
- pool_addfileprovides_ids(repo->pool, 0, &fileinfos[nfileinfos].addedfileprovides);
- if (fileinfos[nfileinfos].addedfileprovides)
- nfileinfos++;
+ pool_freeidhashes(repo->pool); /* free some mem */
if (basename)
{
- struct keyfilter_other_data kd;
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_REPODATAS(repo, i, data)
{
for (j = 1, key = data->keys + j; j < data->nkeys; j++, key++)
{
- const char *keyname = id2str(repo->pool, key->name);
+ const char *keyname = pool_id2str(repo->pool, key->name);
if (key->name == SOLVABLE_DISKUSAGE)
has_DU = 1;
if (key->name == SOLVABLE_FILELIST)
break;
if (k < nlanguages)
continue;
- languages = sat_realloc2(languages, nlanguages + 1, sizeof(char *));
+ languages = solv_realloc2(languages, nlanguages + 1, sizeof(char *));
languages[nlanguages++] = strdup(keyname + l);
}
}
- fileinfos = sat_zextend(fileinfos, nfileinfos, nlanguages + 2, sizeof(Repodatafile), REPODATAFILE_BLOCK);
/* write language subfiles */
for (i = 0; i < nlanguages; i++)
{
perror(fn);
exit(1);
}
- repo_write(repo, fp, keyfilter_language, languages[i], fileinfos + nfileinfos, 0);
- fileinfos[nfileinfos].location = strdup(fn);
+ write_info(repo, fp, keyfilter_language, languages[i], info, fn);
fclose(fp);
- nfileinfos++;
+ kd.haveexternal = 1;
}
/* write DU subfile */
if (has_DU)
perror(fn);
exit(1);
}
- repo_write(repo, fp, keyfilter_DU, 0, fileinfos + nfileinfos, 0);
- fileinfos[nfileinfos].location = strdup(fn);
+ write_info(repo, fp, keyfilter_DU, 0, info, fn);
fclose(fp);
- nfileinfos++;
+ kd.haveexternal = 1;
}
/* write filelist */
if (has_FL)
perror(fn);
exit(1);
}
- repo_write(repo, fp, keyfilter_FL, 0, fileinfos + nfileinfos, 0);
- fileinfos[nfileinfos].location = strdup(fn);
+ write_info(repo, fp, keyfilter_FL, 0, info, fn);
fclose(fp);
- nfileinfos++;
+ kd.haveexternal = 1;
}
/* write everything else */
sprintf(fn, "%s.solv", basename);
}
kd.languages = languages;
kd.nlanguages = nlanguages;
- repo_write(repo, fp, keyfilter_other, &kd, nfileinfos ? fileinfos : 0, nfileinfos);
- fclose(fp);
- for (i = 0; i < nlanguages; i++)
- free(languages[i]);
- sat_free(languages);
- for (i = 0; i < nfileinfos; i++)
+ repodata_internalize(info);
+ if (repo_write_filtered(repo, fp, keyfilter_other, &kd, 0) != 0)
+ {
+ fprintf(stderr, "repo_write failed\n");
+ exit(1);
+ }
+ if (fclose(fp) != 0)
{
- sat_free(fileinfos[i].addedfileprovides);
- sat_free(fileinfos[i].location);
- sat_free(fileinfos[i].keys);
+ perror("fclose");
+ exit(1);
}
- sat_free(fileinfos);
- return 0;
+ for (i = 0; i < nlanguages; i++)
+ free(languages[i]);
+ solv_free(languages);
+ repodata_free(info);
}
if (attrname)
{
- fileinfos = sat_zextend(fileinfos, nfileinfos, 1, sizeof(Repodatafile), REPODATAFILE_BLOCK);
+ FILE *fp;
test_separate = 1;
- FILE *fp = fopen (attrname, "w");
- repo_write(repo, fp, keyfilter_attr, 0, fileinfos + nfileinfos, 0);
- fileinfos[nfileinfos].location = strdup(attrname);
+ fp = fopen(attrname, "w");
+ write_info(repo, fp, keyfilter_attr, 0, info, attrname);
fclose(fp);
- nfileinfos++;
+ kd.haveexternal = 1;
}
- repo_write(repo, stdout, keyfilter_solv, 0, nfileinfos ? fileinfos : 0, nfileinfos);
- for (i = 0; i < nfileinfos; i++)
+ repodata_internalize(info);
+ if (repo_write_filtered(repo, stdout, keyfilter_solv, &kd, 0) != 0)
{
- sat_free(fileinfos[i].addedfileprovides);
- sat_free(fileinfos[i].location);
- sat_free(fileinfos[i].keys);
+ fprintf(stderr, "repo_write failed\n");
+ exit(1);
}
- sat_free(fileinfos);
- return 0;
+ repodata_free(info);
}