+ pd->nfilelist = 0;
+ }
+ /* Add self provide, except for source packages. This is harmless
+ to do twice (in case we see the same package twice). */
+ if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
+ s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
+ repo_rewrite_suse_deps(s, freshens);
+ if (pd->diskusageq.count)
+ repodata_add_diskusage(pd->data, handle, &pd->diskusageq);
+}
+
+static Hashtable
+joinhash_init(Repo *repo, Hashval *hmp)
+{
+ Hashval hm = mkmask(repo->nsolvables);
+ Hashtable ht = solv_calloc(hm + 1, sizeof(*ht));
+ Hashval h, hh;
+ Solvable *s;
+ int i;
+
+ FOR_REPO_SOLVABLES(repo, i, s)
+ {
+ hh = HASHCHAIN_START;
+ h = s->name & hm;
+ while (ht[h])
+ h = HASHCHAIN_NEXT(h, hh, hm);
+ ht[h] = i;
+ }
+ *hmp = hm;
+ return ht;
+}
+
+static Solvable *
+joinhash_lookup(Repo *repo, Hashtable ht, Hashval hm, Id name, Id evr, Id arch, Id start)
+{
+ Hashval h, hh;
+
+ if (!name || !arch || !evr)
+ return 0;
+ hh = HASHCHAIN_START;
+ h = name & hm;
+ while (ht[h])
+ {
+ Solvable *s = repo->pool->solvables + ht[h];
+ if (ht[h] >= start && s->name == name && s->evr == evr && s->arch == arch)
+ return s;
+ h = HASHCHAIN_NEXT(h, hh, hm);
+ }
+ return 0;
+}
+
+static Id
+lookup_shared_id(Repodata *data, Id p, Id keyname, Id voidid, int uninternalized)
+{
+ Id r;
+ r = repodata_lookup_type(data, p, keyname);
+ if (r)
+ {
+ if (r == REPOKEY_TYPE_VOID)
+ return voidid;
+ r = repodata_lookup_id(data, p, keyname);
+ if (r)
+ return r;
+ }
+ if (uninternalized)
+ {
+ KeyValue kv;
+ Repokey *key = repodata_lookup_kv_uninternalized(data, p, keyname, &kv);
+ if (!key)
+ return 0;
+ if (key->type == REPOKEY_TYPE_VOID)
+ return voidid;
+ if (key->type == REPOKEY_TYPE_ID)
+ return kv.id;
+ }
+ return 0;
+}
+
+static inline Id
+toevr(Pool *pool, struct parsedata *pd, const char *version, const char *release)
+{
+ return makeevr(pool, !release || (release[0] == '-' && !release[1]) ?
+ version : join2(&pd->jd, version, "-", release));
+}
+
+
+static inline void record_share(struct parsedata *pd, Id handle, Id name, Id evr, Id arch)
+{
+ Repo *repo = pd->repo;
+ int i = handle - repo->start;
+ if (i >= pd->nshare)
+ {
+ pd->share_with = solv_realloc2(pd->share_with, i + 256, sizeof(*pd->share_with));
+ memset(pd->share_with + pd->nshare, 0, (i + 256 - pd->nshare) * sizeof(*pd->share_with));
+ pd->nshare = i + 256;
+ }
+ pd->share_with[i].name = name;
+ pd->share_with[i].evr = evr;
+ pd->share_with[i].arch = arch;
+}
+
+static void process_shares(struct parsedata *pd)
+{
+ Pool *pool = pd->pool;
+ Repo *repo = pd->repo;
+ Repodata *data = pd->data;
+ int i, last_found;
+ Map keyidmap;
+
+ map_init(&keyidmap, data->nkeys);
+ for (i = 1; i < data->nkeys; i++)
+ {
+ Id keyname = data->keys[i].name;
+ if (keyname == SOLVABLE_INSTALLSIZE || keyname == SOLVABLE_DISKUSAGE || keyname == SOLVABLE_FILELIST)
+ continue;
+ if (keyname == SOLVABLE_MEDIADIR || keyname == SOLVABLE_MEDIAFILE || keyname == SOLVABLE_MEDIANR)
+ continue;
+ if (keyname == SOLVABLE_DOWNLOADSIZE || keyname == SOLVABLE_CHECKSUM)
+ continue;
+ if (keyname == SOLVABLE_SOURCENAME || keyname == SOLVABLE_SOURCEARCH || keyname == SOLVABLE_SOURCEEVR)
+ continue;
+ if (keyname == SOLVABLE_PKGID || keyname == SOLVABLE_HDRID || keyname == SOLVABLE_LEADSIGID)
+ continue;
+ if (keyname == SUSETAGS_SHARE_NAME || keyname == SUSETAGS_SHARE_EVR || keyname == SUSETAGS_SHARE_ARCH)
+ continue;
+ MAPSET(&keyidmap, i);
+ }
+ last_found = 0;
+ for (i = 0; i < pd->nshare; i++)
+ {
+ unsigned int n, nn;
+ Solvable *found = 0;
+ if (!pd->share_with[i].name)
+ continue;
+ for (n = repo->start, nn = repo->start + last_found; n < repo->end; n++, nn++)