- put sat_xfopen in libsatsolverext
authorMichael Schroeder <mls@suse.de>
Fri, 28 Jan 2011 14:52:50 +0000 (15:52 +0100)
committerMichael Schroeder <mls@suse.de>
Fri, 28 Jan 2011 14:55:08 +0000 (15:55 +0100)
- commit current state of new python bindings and python example package manager
  still work in progress, though

examples/pysolv.py [new file with mode: 0644]
examples/solv.c
examples/solv.i [new file with mode: 0644]
ext/CMakeLists.txt
ext/sat_xfopen.c [moved from tools/common_myfopen.h with 73% similarity]
ext/sat_xfopen.h [new file with mode: 0644]
tools/installcheck.c
tools/patchcheck.c
tools/rpmmd2solv.c
tools/susetags2solv.c

diff --git a/examples/pysolv.py b/examples/pysolv.py
new file mode 100644 (file)
index 0000000..e14fd84
--- /dev/null
@@ -0,0 +1,444 @@
+#!/usr/bin/python
+
+import sys
+import os
+import glob
+import solv
+import re
+import tempfile
+import time
+import subprocess
+import fnmatch
+from stat import *
+from solv import Pool, Repo, Dataiterator, Job
+from iniparse import INIConfig
+from optparse import OptionParser
+
+def calc_checksum_stat(stat, type=solv.REPOKEY_TYPE_SHA256):
+    chksum = solv.Chksum(type)
+    chksum.add("1.1")
+    chksum.add(str(stat[ST_DEV]))
+    chksum.add(str(stat[ST_INO]))
+    chksum.add(str(stat[ST_SIZE]))
+    chksum.add(str(stat[ST_MTIME]))
+    return chksum.raw()
+
+def calc_checksum_fp(fp, type=solv.REPOKEY_TYPE_SHA256):
+    chksum = solv.Chksum(type)
+    chksum.addfp(fp)
+    return chksum.raw()
+
+def calccachepath(repo, repoext = None):
+    path = re.sub(r'^\.', '_', repo['alias'])
+    if repoext:
+       path += "_" + repoext + ".solvx"
+    else:
+       path += ".solv"
+    return "/var/cache/solv/" + re.sub(r'[/]', '_', path)
+    
+def usecachedrepo(repo, repoext, cookie, mark=False):
+    handle = repo['handle']
+    try: 
+        repopath = calccachepath(repo, repoext)
+        f = open(repopath, 'r')
+       f.seek(-32, os.SEEK_END)
+       fcookie = f.read(32)
+       if len(fcookie) != 32:
+           return False
+       if cookie and fcookie != cookie:
+           return False
+       if repo['alias'] != '@System' and not repoext:
+           f.seek(-32 * 2, os.SEEK_END)
+           fextcookie = f.read(32)
+           if len(fextcookie) != 32:
+               return False
+        f.seek(0)
+        flags = 0
+        if repoext:
+            flags = Repo.REPO_USE_LOADING|Repo.REPO_EXTEND_SOLVABLES
+            if repoext != 'DL':
+               flags |= Repo.REPO_LOCALPOOL
+        if not repo['handle'].add_solv(f, flags):
+           return False
+       if repo['alias'] != '@System' and not repoext:
+           repo['cookie'] = fcookie
+           repo['extcookie'] = fextcookie
+       if mark:
+           # no futimes in python?
+           try:
+               os.utime(repopath, None)
+           except e:
+               pass
+    except IOError, e:
+       return False
+    return True
+
+def writecachedrepo(repo, repoext, cookie, info=None):
+    try:
+       if not os.path.isdir("/var/cache/solv"):
+           os.mkdir("/var/cache/solv", 0755);
+       (fd, tmpname) = tempfile.mkstemp(prefix='.newsolv-', dir='/var/cache/solv')
+       os.fchmod(fd, 0444)
+        f = os.fdopen(fd, 'w+')
+       if not info:
+           repo['handle'].write(f)
+       elif repoext:
+           info.write(f)
+       else:
+           repo['handle'].write_first_repodata(f)
+       if repo['alias'] != '@System' and not repoext:
+           if 'extcookie' not in repo:
+               # create unique id
+               extcookie = calc_checksum_stat(os.fstat(f.fileno()))
+               extcookie = ''.join(chr(ord(s)^ord(c)) for s,c in zip(extcookie, cookie))
+               if ord(extcookie[0]) == 0:
+                   extcookie[0] = chr(1)
+               repo['extcookie'] = extcookie
+           f.write(repo['extcookie'])
+       f.write(cookie)
+       f.close()
+       os.rename(tmpname, calccachepath(repo, repoext))
+    except IOError, e:
+       if tmpname:
+           os.unlink(tmpname)
+
+def curlfopen(repo, file, uncompress, chksum, chksumtype, badchecksum=None):
+    baseurl = repo['baseurl']
+    url = re.sub(r'/$', '', baseurl) + '/' + file;
+    f = tempfile.TemporaryFile()
+    st = subprocess.call(['curl', '-f', '-s', '-L', url], stdout=f.fileno())
+    if os.lseek(f.fileno(), 0, os.SEEK_CUR) == 0 and (st == 0 or not chksumtype):
+       return None
+    os.lseek(f.fileno(), 0, os.SEEK_SET)
+    if st:
+       print "%s: download error %d" % (file, st)
+       if badchecksum:
+           badchecksum['True'] = 'True'
+        return None
+    if chksumtype:
+       fchksum = solv.Chksum(chksumtype)
+       if not fchksum:
+           print "%s: unknown checksum type" % file
+           if badchecksum:
+               badchecksum['True'] = 'True'
+           return None
+       fchksum.addfd(f.fileno())
+       if not fchksum.matches(chksum):
+           print "%s: checksum mismatch" % file
+           if badchecksum:
+               badchecksum['True'] = 'True'
+           return None
+    if uncompress:
+       return solv.xfopen_fd(file, os.dup(f.fileno()))
+    return solv.xfopen_fd("", os.dup(f.fileno()))
+
+def repomd_find(repo, what):
+    di = repo['handle'].dataiterator_new(solv.SOLVID_META, solv.REPOSITORY_REPOMD_TYPE, what, Dataiterator.SEARCH_STRING)
+    di.prepend_keyname(solv.REPOSITORY_REPOMD);
+    for d in di:
+        d.setpos_parent()
+        filename = d.pool.lookup_str(solv.SOLVID_POS, solv.REPOSITORY_REPOMD_LOCATION);
+        chksum, chksumtype = d.pool.lookup_bin_checksum(solv.SOLVID_POS, solv.REPOSITORY_REPOMD_CHECKSUM);
+        if filename and not chksumtype:
+           print "no %s file checksum!" % filename
+           filename = None
+           chksum = None
+        if filename:
+            return (filename, chksum, chksumtype)
+    return (None, None, None)
+
+def validarch(pool, arch):
+    if not arch:
+       return False
+    id = pool.str2id(arch, False)
+    if not id:
+       return False
+    return pool.isknownarch(id)
+
+def limitjobs(pool, jobs, flags, evr):
+    njobs = []
+    for j in jobs:
+       how = j.how;
+       sel = how & Job.SOLVER_SELECTMASK
+       what = pool.rel2id(j.what, evr, flags)
+        if flags == solv.REL_ARCH:
+           how |= Job.SOLVER_SETARCH
+       if flags == solv.REL_EQ and sel == Job.SOLVER_SOLVABLE_NAME:
+           if pool.id2str(evr).find('-') >= 0:
+               how |= Job.SOLVER_SETEVR
+           else:
+               how |= Job.SOLVER_SETEV
+       njobs.append(Job(how, what))
+    return njobs
+
+def limitjobs_arch(pool, jobs, flags, evr):
+    m = re.match(r'(.+)\.(.+?)$', evr)
+    if m and validarch(pool, m.group(2)):
+       jobs = limitjobs(pool, jobs, solv.REL_ARCH, pool.str2id(m.group(2)))
+       return limitjobs(pool, jobs, flags, pool.str2id(m.group(1)))
+    else:
+       return limitjobs(pool, jobs, flags, pool.str2id(evr))
+
+def mkjobs(pool, cmd, arg):
+    if len(arg) and arg[0] == '/':
+        if re.search(r'[[*?]', arg):
+           type = Dataiterator.SEARCH_GLOB
+       else:
+           type = Dataiterator.SEARCH_STRING
+        if cmd == 'rm' or cmd == 'erase':
+           di = pool.installed.dataiterator_new(0, solv.SOLVABLE_FILELIST, arg, type | Dataiterator.SEARCH_FILES|Dataiterator.SEARCH_COMPLETE_FILELIST)
+       else:
+           di = pool.dataiterator_new(0, solv.SOLVABLE_FILELIST, arg, type | Dataiterator.SEARCH_FILES|Dataiterator.SEARCH_COMPLETE_FILELIST)
+        matches = []
+       for d in di:
+           s = d.solvable
+           if s and s.installable():
+               matches.append(s.id)
+               di.skip_solvable()      # one match is enough
+       if len(matches):
+           print "[using file list match for '%s']" % arg
+           if len(matches) > 1:
+               return [ Job(Job.SOLVER_SOLVABLE_ONE_OF, pool.towhatprovides(matches)) ]
+           else:
+               return [ Job(Job.SOLVER_SOLVABLE | Job.SOLVER_NOAUTOSET, matches[0]) ]
+    m = re.match(r'(.+?)\s*([<=>]+)\s*(.+?)$', arg)
+    if m:
+       (name, rel, evr) = m.group(1, 2, 3);
+       flags = 0
+       if rel.find('<') >= 0: flags |= solv.REL_LT
+       if rel.find('=') >= 0: flags |= solv.REL_EQ 
+       if rel.find('>') >= 0: flags |= solv.REL_GT
+       jobs = depglob(pool, name, True, True)
+       if len(jobs):
+           return limitjobs(pool, jobs, flags, pool.str2id(evr))
+       m = re.match(r'(.+)\.(.+?)$', name)
+       if m and validarch(pool, m.group(2)):
+           jobs = depglob(pool, m.group(1), True, True)
+           if len(jobs):
+               jobs = limitjobs(pool, jobs, solv.REL_ARCH, pool.str2id(m.group(2)))
+               return limitjobs(pool, jobs, flags, pool.str2id(evr))
+    else:
+       jobs = depglob(pool, arg, True, True)
+        if len(jobs):
+           return jobs
+       m = re.match(r'(.+)\.(.+?)$', arg)
+       if m and validarch(pool, m.group(2)):
+           jobs = depglob(pool, m.group(1), True, True)
+           if len(jobs):
+               return limitjobs(pool, jobs, solv.REL_ARCH, pool.str2id(m.group(2)))
+       m = re.match(r'(.+)-(.+?)$', arg)
+       if m:
+           jobs = depglob(pool, m.group(1), True, False)
+           if len(jobs):
+               return limitjobs_arch(pool, jobs, solv.REL_EQ, m.group(2))
+       m = re.match(r'(.+)-(.+?-.+?)$', arg)
+       if m:
+           jobs = depglob(pool, m.group(1), True, False)
+           if len(jobs):
+               return limitjobs_arch(pool, jobs, solv.REL_EQ, m.group(2))
+    return []
+    
+           
+def depglob(pool, name, globname, globdep):
+    id = pool.str2id(name, False)
+    if id:
+       match = False
+       for s in pool.providers(id):
+           if globname and s.nameid == id:
+               return [ Job(Job.SOLVER_SOLVABLE_NAME, id) ]
+           match = True
+       if match:
+           if globname and globdep:
+               print "[using capability match for '%s']" % name
+           return [ Job(Job.SOLVER_SOLVABLE_PROVIDES, id) ]
+    if not re.search(r'[[*?]', name):
+       return []
+    if globname:
+       # try name glob
+       idmatches = {}
+       for s in pool.solvables:
+           if s.installable() and fnmatch.fnmatch(s.name, name):
+               idmatches[s.nameid] = True
+       if len(idmatches):
+           return [ Job(Job.SOLVER_SOLVABLE_NAME, id) for id in sorted(idmatches.keys()) ]
+    if globdep:
+       # try dependency glob
+       idmatches = {}
+       for id in pool.allprovidingids():
+           if fnmatch.fnmatch(pool.id2str(id), name):
+               idmatches[id] = True
+       if len(idmatches):
+           print "[using capability match for '%s']" % name
+           return [ Job(Job.SOLVER_SOLVABLE_PROVIDES, id) for id in sorted(idmatches.keys()) ]
+    return []
+    
+
+parser = OptionParser(usage="usage: solv.py [options] COMMAND")
+(options, args) = parser.parse_args()
+if not args:
+    parser.print_help(sys.stderr)
+    sys.exit(1)
+
+cmd = args[0]
+args = args[1:]
+
+pool = solv.Pool()
+pool.setarch(os.uname()[4])
+
+repos = []
+for reposdir in ["/etc/zypp/repos.d"]:
+    if not os.path.isdir(reposdir):
+       continue
+    for reponame in sorted(glob.glob('%s/*.repo' % reposdir)):
+       cfg = INIConfig(open(reponame))
+       for alias in cfg:
+           repo = cfg[alias]
+           repo['alias'] = alias
+           if 'priority' not in repo:
+               repo['priority'] = 99
+           if 'autorefresh' not in repo:
+               repo['autorefresh'] = 1
+           repo['metadata_expire'] = 900
+           repos.append(repo)
+
+print "rpm database:",
+sysrepo = { 'alias': '@System' }
+sysrepo['handle'] = pool.add_repo(sysrepo['alias'])
+sysrepo['handle'].appdata = sysrepo
+pool.installed = sysrepo['handle']
+sysrepostat = os.stat("/var/lib/rpm/Packages")
+sysrepocookie = calc_checksum_stat(sysrepostat)
+if usecachedrepo(sysrepo, None, sysrepocookie):
+    print "cached"
+else:
+    print "reading"
+    sysrepo['handle'].add_products("/etc/products.d", Repo.REPO_NO_INTERNALIZE);
+    sysrepo['handle'].add_rpmdb(None)
+    writecachedrepo(sysrepo, None, sysrepocookie)
+
+for repo in repos:
+    if not int(repo.enabled):
+       continue
+    repo['handle'] = pool.add_repo(repo['alias'])
+    repo['handle'].appdata = repo
+    repo['handle'].priority = 99 - repo['priority']
+    if repo['autorefresh']:
+       dorefresh = True
+    if dorefresh:
+       try:
+           st = os.stat(calccachepath(repo))
+           if time.time() - st[ST_MTIME] < repo['metadata_expire']:
+               dorefresh = False
+       except OSError, e:
+           pass
+    if not dorefresh and usecachedrepo(repo, None, None):
+       print "repo: '%s': cached" % repo['alias']
+       continue
+
+    badchecksum = {}
+
+    print "rpmmd repo '%s':" % repo['alias'],
+    sys.stdout.flush()
+    f = curlfopen(repo, "repodata/repomd.xml", False, None, None)
+    if not f:
+       print "no repomd.xml file, skipped"
+       repo['handle'].free(True)
+       del repo['handle']
+       continue
+    repo['cookie'] = calc_checksum_fp(f)
+    if usecachedrepo(repo, None, repo['cookie'], True):
+       print "cached"
+        solv.xfclose(f)
+       continue
+    repo['handle'].add_repomdxml(f, 0)
+    solv.xfclose(f)
+    print "fetching"
+    (filename, filechksum, filechksumtype) = repomd_find(repo, 'primary')
+    if filename:
+       f = curlfopen(repo, filename, True, filechksum, filechksumtype, badchecksum)
+       if f:
+           repo['handle'].add_rpmmd(f, None, 0)
+           solv.xfclose(f)
+       if badchecksum:
+           continue    # hopeless, need good primary
+    (filename, filechksum, filechksumtype) = repomd_find(repo, 'updateinfo')
+    if filename:
+       f = curlfopen(repo, filename, True, filechksum, filechksumtype, badchecksum)
+       if f:
+           repo['handle'].add_updateinfoxml(f, 0)
+           solv.xfclose(f)
+    # if the checksum was bad we work with the data we got, but don't cache it
+    if 'True' not in badchecksum:
+       writecachedrepo(repo, None, repo['cookie'])
+    
+if cmd == 'se' or cmd == 'search':
+    matches = {}
+    print "searching for", args[1]
+    di = pool.dataiterator_new(0, solv.SOLVABLE_NAME, args[1], Dataiterator.SEARCH_SUBSTRING|Dataiterator.SEARCH_NOCASE)
+    for d in di:
+       matches[di.solvid] = True
+    for solvid in sorted(matches.keys()):
+       print " - %s: %s" % (pool.solvid2str(solvid), pool.lookup_str(solvid, solv.SOLVABLE_SUMMARY))
+    exit(0)
+
+# XXX: insert rewrite_repos function
+
+pool.addfileprovides()
+pool.createwhatprovides()
+
+jobs = []
+for arg in args:
+    argjob = mkjobs(pool, cmd, arg)
+    jobs += argjob
+
+if cmd == 'li' or cmd == 'list' or cmd == 'info':
+    if not jobs:
+       print "no package matched."
+       exit(1)
+    for job in jobs:
+       for s in pool.jobsolvables(job):
+           if cmd == 'info':
+               print "Name:        %s" % s.str()
+               print "Repo:        %s" % s.repo.name
+               print "Summary:     %s" % s.lookup_str(solv.SOLVABLE_SUMMARY)
+               str = s.lookup_str(solv.SOLVABLE_URL)
+               if str:
+                   print "Url:         %s" % str
+               str = s.lookup_str(solv.SOLVABLE_LICENSE)
+               if str:
+                   print "License:     %s" % str
+               print "Description:\n%s" % s.lookup_str(solv.SOLVABLE_DESCRIPTION)
+               print
+           else:
+               print "  - %s [%s]" % (s.str(), s.repo.name)
+               print "    %s" % s.lookup_str(solv.SOLVABLE_SUMMARY)
+    exit(0)
+
+if cmd == 'in' or cmd == 'install' or cmd == 'rm' or cmd == 'erase' or cmd == 'up':
+    if cmd == 'up' and not jobs:
+       jobs = [ Job(Job.SOLVER_SOLVABLE_ALL, 0) ]
+    if not jobs:
+       print "no package matched."
+       exit(1)
+    for job in jobs:
+       if cmd == 'up':
+           if job.how == Job.SOLVER_SOLVABLE_ALL or filter(lambda s: s.isinstalled(), pool.jobsolvables(job)):
+               job.how |= Job.SOLVER_UPDATE
+           else:
+               job.how |= Job.SOLVER_INSTALL
+       if cmd == 'in' or cmd == 'install':
+           job.how |= Job.SOLVER_INSTALL
+       elif cmd == 'rm' or cmd == 'erase':
+           job.how |= Job.SOLVER_ERASE
+
+    #pool.set_debuglevel(2)
+    solver = pool.create_solver()
+    problems = solver.solve(jobs)
+    if problems:
+       for problem in problems:
+           print "Problem %d:" % problem.id
+           r = problem.findproblemrule()
+           type, source, target, dep = solver.ruleinfo(r)
+           print type, source, target, dep
+    
+# vim: sw=4 et
index 8d35117..b277617 100644 (file)
@@ -72,8 +72,7 @@
 #include "repo_deltainfoxml.h"
 #include "repo_content.h"
 #include "pool_fileconflicts.h"
-
-#include "../tools/common_myfopen.h"
+#include "sat_xfopen.h"
 
 #ifdef FEDORA
 # define REPOINFO_PATH "/etc/yum.repos.d"
@@ -859,20 +858,7 @@ curlfopen(struct repoinfo *cinfo, const char *file, int uncompress, const unsign
       return 0;
     }
   if (uncompress)
-    {
-      char tmpl[100];
-      gzFile *gzf;
-
-      sprintf(tmpl, "/dev/fd/%d", fd);
-      gzf = gzopen(tmpl, "r");
-      close(fd);
-      if (!gzf)
-       {
-         fprintf(stderr, "could not open /dev/fd/%d, /proc not mounted?\n", fd);
-         exit(1);
-       }
-      return mygzfopen(gzf);
-    }
+    return sat_xfopen_fd(".gz", fd);
   fcntl(fd, F_SETFD, FD_CLOEXEC);
   return fdopen(fd, "r");
 }
@@ -2859,7 +2845,8 @@ main(int argc, char **argv)
       /* list mode, no solver needed */
       for (i = 0; i < job.count; i += 2)
        {
-         FOR_JOB_SELECT(p, pp, job.elements[i], job.elements[i + 1])
+         Id how = job.elements[i] & SOLVER_SELECTMASK;
+         FOR_JOB_SELECT(p, pp, how, job.elements[i + 1])
            {
              Solvable *s = pool_id2solvable(pool, p);
              if (mainmode == MODE_INFO)
diff --git a/examples/solv.i b/examples/solv.i
new file mode 100644 (file)
index 0000000..4aaeba4
--- /dev/null
@@ -0,0 +1,862 @@
+%module solv
+
+%typemap(in) (Id *idarray, int idarraylen) {
+  /* Check if is a list */
+  if (PyList_Check($input)) {
+    int size = PyList_Size($input);
+    int i = 0;
+    $1 = (Id *)sat_malloc2(size, sizeof(Id));
+    for (i = 0; i < size; i++) {
+      PyObject *o = PyList_GetItem($input,i);
+      int v;
+      int e = SWIG_AsVal_int(o, &v);
+      if (!SWIG_IsOK(e)) {
+        SWIG_exception_fail(SWIG_ArgError(e), "list must contain integers");
+        sat_free($1);
+        return NULL;
+      }
+      $1[i] = v;
+    }
+    $2 = size;
+  } else {
+    PyErr_SetString(PyExc_TypeError,"not a list");
+    return NULL;
+  }
+}
+%typemap(freearg) (Id *idarray, int idarraylen) {
+  sat_free($1);
+}
+
+%typemap(in) Queue {
+  /* Check if is a list */
+  queue_init(&$1);
+  if (PyList_Check($input)) {
+    int size = PyList_Size($input);
+    int i = 0;
+    for (i = 0; i < size; i++) {
+      PyObject *o = PyList_GetItem($input,i);
+      int v;
+      int e = SWIG_AsVal_int(o, &v);
+      if (!SWIG_IsOK(e)) {
+        SWIG_exception_fail(SWIG_ArgError(e), "list must contain only integers");
+        queue_free(&$1);
+        return NULL;
+      }
+      queue_push(&$1, v);
+    }
+  } else {
+    PyErr_SetString(PyExc_TypeError,"not a list");
+    return NULL;
+  }
+}
+%typemap(out) Queue {
+  int i;
+  PyObject *o = PyList_New($1.count);
+  for (i = 0; i < $1.count; i++)
+    PyList_SetItem(o, i, SWIG_From_int($1.elements[i]));
+  queue_free(&$1);
+  $result = o;
+}
+%typemap(arginit) Queue {
+  queue_init(&$1);
+}
+%typemap(freearg) Queue {
+  queue_free(&$1);
+}
+
+
+%include "cdata.i"
+%include "file.i"
+%include "typemaps.i"
+
+%{
+#include "stdio.h"
+#include "pool.h"
+#include "solver.h"
+#include "repo_solv.h"
+#include "chksum.h"
+
+#include "repo_rpmdb.h"
+#include "repo_rpmmd.h"
+#include "repo_write.h"
+#include "repo_products.h"
+#include "repo_susetags.h"
+#include "repo_updateinfoxml.h"
+#include "repo_deltainfoxml.h"
+#include "repo_repomdxml.h"
+#include "repo_content.h"
+#include "sat_xfopen.h"
+
+#define true 1
+#define false 1
+
+typedef struct chksum Chksum;
+typedef int bool;
+
+typedef struct {
+  Pool* pool;
+  Id id;
+} xSolvable;
+
+typedef struct {
+  Pool *pool;
+  Id id;
+} Pool_solvable_iterator;
+
+typedef struct {
+  Pool *pool;
+  Id id;
+} Pool_repo_iterator;
+
+typedef struct {
+  Repo *repo;
+  Id id;
+} Repo_solvable_iterator;
+
+typedef struct {
+  Id how;
+  Id what;
+} Job;
+
+typedef struct {
+  Solver *solv;
+  Id id;
+} Problem;
+
+static inline xSolvable *xSolvable_create(Pool *pool, Id id)
+{
+  xSolvable *s = sat_calloc(sizeof(*s), 1);
+  s->pool = pool;
+  s->id = id;
+  return s;
+}
+
+%}
+
+typedef int Id;
+
+%include "knownid.h"
+
+# from repodata.h
+%constant Id SOLVID_META;
+%constant Id SOLVID_POS;
+
+%constant int REL_EQ;
+%constant int REL_GT;
+%constant int REL_LT;
+%constant int REL_ARCH;
+
+
+# put before pool/repo so we can access the constructor
+%nodefaultctor Dataiterator;
+%nodefaultdtor Dataiterator;
+typedef struct _Dataiterator {
+  Pool * const pool;
+  Repo * const repo;
+  const Id solvid;
+} Dataiterator;
+
+%nodefaultdtor Pool;
+typedef struct {
+} Pool;
+
+%nodefaultctor Repo;
+%nodefaultdtor Repo;
+typedef struct _Repo {
+  const char * const name;
+  int priority;
+  int subpriority;
+  PyObject *appdata;
+} Repo;
+
+%nodefaultctor xSolvable;
+typedef struct {
+  Pool* const pool;
+  const Id id;
+} xSolvable;
+
+%nodefaultctor Pool_solvable_iterator;
+typedef struct {} Pool_solvable_iterator;
+%nodefaultctor Pool_repo_iterator;
+typedef struct {} Pool_repo_iterator;
+%nodefaultctor Repo_solvable_iterator;
+typedef struct {} Repo_solvable_iterator;
+
+%nodefaultctor Solver;
+%nodefaultdtor Solver;
+typedef struct {
+  bool ignorealreadyrecommended;
+  bool dosplitprovides;
+  bool fixsystem;
+  bool allowuninstall;
+  bool distupgrade;
+  bool allowdowngrade;
+  bool allowarchchange;
+  bool allowvendorchange;
+} Solver;
+
+typedef struct chksum {} Chksum;
+
+%rename(xfopen) sat_xfopen;
+%rename(xfopen_fd) sat_xfopen_fd;
+%rename(xfclose) sat_xfclose;
+
+FILE *sat_xfopen(const char *fn);
+FILE *sat_xfopen_fd(const char *fn, int fd);
+%inline {
+  int sat_xfclose(FILE *fp) {
+    return fclose(fp);
+  }
+}
+typedef struct {
+  Id how;
+  Id what;
+} Job;
+
+typedef struct {
+  Solver *solv;
+  Id id;
+} Problem;
+
+%extend Job {
+  static const Id SOLVER_SOLVABLE = SOLVER_SOLVABLE;
+  static const Id SOLVER_SOLVABLE_NAME = SOLVER_SOLVABLE_NAME;
+  static const Id SOLVER_SOLVABLE_PROVIDES = SOLVER_SOLVABLE_PROVIDES;
+  static const Id SOLVER_SOLVABLE_ONE_OF = SOLVER_SOLVABLE_ONE_OF;
+  static const Id SOLVER_SOLVABLE_REPO = SOLVER_SOLVABLE_REPO;
+  static const Id SOLVER_SOLVABLE_ALL = SOLVER_SOLVABLE_ALL;
+  static const Id SOLVER_SELECTMASK = SOLVER_SELECTMASK;
+  static const Id SOLVER_NOOP = SOLVER_NOOP;
+  static const Id SOLVER_INSTALL = SOLVER_INSTALL;
+  static const Id SOLVER_ERASE = SOLVER_ERASE;
+  static const Id SOLVER_UPDATE = SOLVER_UPDATE;
+  static const Id SOLVER_WEAKENDEPS = SOLVER_WEAKENDEPS;
+  static const Id SOLVER_NOOBSOLETES = SOLVER_NOOBSOLETES;
+  static const Id SOLVER_LOCK = SOLVER_LOCK;
+  static const Id SOLVER_DISTUPGRADE = SOLVER_DISTUPGRADE;
+  static const Id SOLVER_VERIFY = SOLVER_VERIFY;
+  static const Id SOLVER_DROP_ORPHANED = SOLVER_DROP_ORPHANED;
+  static const Id SOLVER_USERINSTALLED = SOLVER_USERINSTALLED;
+  static const Id SOLVER_JOBMASK = SOLVER_JOBMASK;
+  static const Id SOLVER_WEAK = SOLVER_WEAK;
+  static const Id SOLVER_ESSENTIAL = SOLVER_ESSENTIAL;
+  static const Id SOLVER_CLEANDEPS = SOLVER_CLEANDEPS;
+  static const Id SOLVER_SETEV = SOLVER_SETEV;
+  static const Id SOLVER_SETEVR = SOLVER_SETEVR;
+  static const Id SOLVER_SETARCH = SOLVER_SETARCH;
+  static const Id SOLVER_SETVENDOR = SOLVER_SETVENDOR;
+  static const Id SOLVER_SETREPO = SOLVER_SETREPO;
+  static const Id SOLVER_NOAUTOSET = SOLVER_NOAUTOSET;
+  static const Id SOLVER_SETMASK = SOLVER_SETMASK;
+
+  Job(Id how, Id what) {
+    Job *job = sat_calloc(sizeof(*job), 1);
+    job->how = how;
+    job->what = what;
+    return job;
+  }
+}
+
+%extend Chksum {
+  Chksum(Id type) {
+    return (Chksum *)sat_chksum_create(type);
+  }
+  ~Chksum() {
+    sat_chksum_free($self, 0);
+  }
+  void add(const char *str) {
+    sat_chksum_add($self, str, strlen((char *)$self));
+  }
+  void addfp(FILE *fp) {
+    char buf[4096];
+    int l;
+    while ((l = fread(buf, 1, sizeof(buf), fp)) > 0)
+      sat_chksum_add($self, buf, l);
+    rewind(fp);         /* convenience */
+  }
+  void addfd(int fd) {
+    char buf[4096];
+    int l;
+    while ((l = read(fd, buf, sizeof(buf))) > 0)
+      sat_chksum_add($self, buf, l);
+    lseek(fd, 0, 0);    /* convenience */
+  }
+  bool matches(char *othersum) {
+    int l;
+    unsigned char *b;
+    b = sat_chksum_get($self, &l);
+    return memcmp(b, (void *)othersum, l) == 0;
+  }
+  SWIGCDATA raw() {
+    int l;
+    unsigned char *b;
+    b = sat_chksum_get($self, &l);
+    return cdata_void((void *)b, l);
+  }
+}
+
+
+
+%extend Pool {
+  Pool() {
+    Pool *pool = pool_create();
+    return pool;
+  }
+  ~Pool() {
+  }
+  void set_debuglevel(int level) {
+    pool_setdebuglevel($self, level);
+  }
+  Id str2id(const char *str, int create=1) {
+    return str2id($self, str, create);
+  }
+  const char *id2str(Id id) {
+    return id2str($self, id);
+  }
+  const char *dep2str(Id id) {
+    return dep2str($self, id);
+  }
+  Id rel2id(Id name, Id evr, int flags, int create=1) {
+    return rel2id($self, name, evr, flags, create);
+  }
+  void setarch(const char *arch) {
+    pool_setarch($self, arch);
+  }
+  Repo *add_repo(const char *name) {
+    return repo_create($self, name);
+  }
+  const char *lookup_str(Id entry, Id keyname) {
+    return pool_lookup_str($self, entry, keyname);
+  }
+  Id lookup_id(Id entry, Id keyname) {
+    return pool_lookup_id($self, entry, keyname);
+  }
+  unsigned int lookup_num(Id entry, Id keyname, unsigned int notfound = 0) {
+    return pool_lookup_num($self, entry, keyname, notfound);
+  }
+  bool lookup_void(Id entry, Id keyname) {
+    return pool_lookup_void($self, entry, keyname);
+  }
+  SWIGCDATA lookup_bin_checksum(Id entry, Id keyname, Id *OUTPUT) {
+    int l;
+    const unsigned char *b;
+    *OUTPUT = 0;
+    b = pool_lookup_bin_checksum($self, entry, keyname, OUTPUT);
+    if (!b)
+      return cdata_void(0, 0);
+    return cdata_void((char *)b, sat_chksum_len(*OUTPUT));
+  }
+  const char *lookup_checksum(Id entry, Id keyname, Id *OUTPUT) {
+    Id type = 0;
+    *OUTPUT = 0;
+    const char *b = pool_lookup_checksum($self, entry, keyname, OUTPUT);
+    return b;
+  }
+  %newobject dataiterator_new;
+  Dataiterator *dataiterator_new(Id p, Id key,  const char *match, int flags) {
+    return new_Dataiterator($self, 0, p, key, match, flags);
+  }
+  const char *solvid2str(Id solvid) {
+    return solvid2str($self, solvid);
+  }
+  void addfileprovides() {
+    pool_addfileprovides($self);
+  }
+  void createwhatprovides() {
+    pool_createwhatprovides($self);
+  }
+  Pool_solvable_iterator * const solvables;
+  %{
+  SWIGINTERN Pool_solvable_iterator * Pool_solvables_get(Pool *pool) {
+    Pool_solvable_iterator *s;
+    s = sat_calloc(sizeof(*s), 1);
+    s->pool = pool;
+    s->id = 0;
+    return s;
+  }
+  %}
+  Pool_repo_iterator * const repos;
+  %{
+  SWIGINTERN Pool_repo_iterator * Pool_repos_get(Pool *pool) {
+    Pool_repo_iterator *s;
+    s = sat_calloc(sizeof(*s), 1);
+    s->pool = pool;
+    s->id = 0;
+    return s;
+  }
+  %}
+  Repo *installed;
+  %{
+  SWIGINTERN void Pool_installed_set(Pool *pool, Repo *installed) {
+    pool_set_installed(pool, installed);
+  }
+  Repo *Pool_installed_get(Pool *pool) {
+    return pool->installed;
+  }
+  %}
+
+  Queue providerids(Id dep) {
+    Pool *pool = $self;
+    Queue q;
+    Id p, pp;
+    queue_init(&q);
+    FOR_PROVIDES(p, pp, dep)
+      queue_push(&q, p);
+    return q;
+  }
+  Queue allprovidingids() {
+    Pool *pool = $self;
+    Queue q;
+    Id id;
+    queue_init(&q);
+    for (id = 1; id < pool->ss.nstrings; id++)
+      if (pool->whatprovides[id])
+        queue_push(&q, id);
+    return q;
+  }
+  # move to job?
+  Queue jobsolvids(Job *job) {
+    Pool *pool = $self;
+    Id p, pp, how;
+    Queue q;
+    queue_init(&q);
+    how = job->how & SOLVER_SELECTMASK;
+    FOR_JOB_SELECT(p, pp, how, job->what)
+      queue_push(&q, p);
+    return q;
+  }
+
+  %pythoncode %{
+    def jobsolvables (self, *args):
+      return [ self.solvables[id] for id in self.jobsolvids(*args) ]
+    def providers(self, *args):
+      return [ self.solvables[id] for id in self.providerids(*args) ]
+  %}
+
+  Id towhatprovides(Queue q) {
+    return pool_queuetowhatprovides($self, &q);
+  }
+  bool isknownarch(Id id) {
+    Pool *pool = $self;
+    if (id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH)
+      return 1;
+    if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id]))
+      return 0;
+    return 1;
+  }
+
+  %newobject create_solver;
+  Solver *create_solver() {
+    return solver_create($self);
+  }
+}
+
+%extend Repo {
+  static const int REPO_REUSE_REPODATA = REPO_REUSE_REPODATA;
+  static const int REPO_NO_INTERNALIZE = REPO_NO_INTERNALIZE;
+  static const int REPO_LOCALPOOL = REPO_LOCALPOOL;
+  static const int REPO_USE_LOADING = REPO_USE_LOADING;
+  static const int REPO_EXTEND_SOLVABLES = REPO_EXTEND_SOLVABLES;
+  static const int SOLV_ADD_NO_STUBS = SOLV_ADD_NO_STUBS;       /* repo_solv */
+
+  void free(int reuseids = 0) {
+    repo_free($self, reuseids);
+  }
+  bool add_solv(const char *name, int flags = 0) {
+    FILE *fp = fopen(name, "r");
+    if (!fp)
+      return 0;
+    int r = repo_add_solv_flags($self, fp, flags);
+    fclose(fp);
+    return r == 0;
+  }
+  bool add_solv(FILE *fp, int flags = 0) {
+    return repo_add_solv_flags($self, fp, flags) == 0;
+  }
+  bool add_products(const char *proddir, int flags = 0) {
+    repo_add_products($self, proddir, 0, flags);
+    return 1;
+  }
+  bool add_rpmmd(FILE *fp, const char *language, int flags = 0) {
+    repo_add_rpmmd($self, fp, language, flags);
+    return 1;
+  }
+  bool add_rpmdb(Repo *ref, int flags = 0) {
+    repo_add_rpmdb($self, ref, 0, flags);
+    return 1;
+  }
+  bool add_susetags(FILE *fp, Id defvendor, const char *language, int flags = 0) {
+    repo_add_susetags($self, fp, defvendor, language, flags);
+    return 1;
+  }
+  bool add_repomdxml(FILE *fp, int flags = 0) {
+    repo_add_repomdxml($self, fp, flags);
+    return 1;
+  }
+  bool add_content(FILE *fp, int flags = 0) {
+    repo_add_content($self, fp, flags);
+    return 1;
+  }
+  bool add_updateinfoxml(FILE *fp, int flags = 0) {
+    repo_add_updateinfoxml($self, fp, flags);
+    return 1;
+  }
+  bool add_deltainfoxml(FILE *fp, int flags = 0) {
+    repo_add_deltainfoxml($self, fp, flags);
+    return 1;
+  }
+  bool write(FILE *fp, int flags = 0) {
+    repo_write($self, fp, repo_write_stdkeyfilter, 0, 0);
+    return 1;
+  }
+  # HACK, remove if no longer needed!
+  bool write_first_repodata(FILE *fp, int flags = 0) {
+    int oldnrepodata = $self->nrepodata;
+    $self->nrepodata = 1;
+    repo_write($self, fp, repo_write_stdkeyfilter, 0, 0);
+    $self->nrepodata = oldnrepodata;
+    return 1;
+  }
+  %newobject dataiterator_new;
+  Dataiterator *dataiterator_new(Id p, Id key,  const char *match, int flags) {
+    return new_Dataiterator($self->pool, $self, p, key, match, flags);
+  }
+
+  Id const id;
+  %{
+  SWIGINTERN Id Repo_id_get(Repo *repo) {
+    return repo->repoid;
+  }
+  %}
+  Repo_solvable_iterator * const solvables;
+  %{
+  SWIGINTERN Repo_solvable_iterator * Repo_solvables_get(Repo *repo) {
+    Repo_solvable_iterator *s;
+    s = sat_calloc(sizeof(*s), 1);
+    s->repo = repo;
+    s->id = 0;
+    return s;
+  }
+  %}
+}
+
+%extend Dataiterator {
+  static const int SEARCH_STRING = SEARCH_STRING;
+  static const int SEARCH_SUBSTRING = SEARCH_SUBSTRING;
+  static const int SEARCH_GLOB = SEARCH_GLOB;
+  static const int SEARCH_REGEX = SEARCH_REGEX;
+  static const int SEARCH_NOCASE = SEARCH_NOCASE;
+  static const int SEARCH_FILES = SEARCH_FILES;
+  static const int SEARCH_COMPLETE_FILELIST = SEARCH_COMPLETE_FILELIST;
+
+  Dataiterator(Pool *pool, Repo *repo, Id p, Id key, const char *match, int flags) {
+    Dataiterator *di = sat_calloc(sizeof(*di), 1);
+    dataiterator_init(di, pool, repo, p, key, match, flags);
+    return di;
+  }
+  ~Dataiterator() {
+    dataiterator_free($self);
+  }
+  Dataiterator *__iter__() {
+    return $self;
+  }
+  %exception next {
+    $action
+    if (!result) {
+      PyErr_SetString(PyExc_StopIteration,"no more matches");
+      return NULL;
+    }
+  }
+  %newobject next;
+  Dataiterator *next() {
+    Dataiterator *ndi;
+    if (!dataiterator_step($self)) {
+      return 0;
+    }
+    ndi = sat_calloc(sizeof(*ndi), 1);
+    dataiterator_init_clone(ndi, $self);
+    return ndi;
+  }
+  void setpos_parent() {
+    dataiterator_setpos_parent($self);
+  }
+  void prepend_keyname(Id key) {
+    dataiterator_prepend_keyname($self, key);
+  }
+  void skip_solvable() {
+    dataiterator_skip_solvable($self);
+  }
+
+  %newobject solvable;
+  xSolvable * const solvable;
+  %{
+  SWIGINTERN xSolvable *Dataiterator_solvable_get(Dataiterator *di) {
+    return di->solvid ? xSolvable_create(di->pool, di->solvid) : 0;
+  }
+  %}
+  Id key_id() {
+    return $self->key->name;
+  }
+  const char *key_idstr() {
+    return id2str($self->pool, $self->key->name);
+  }
+  Id keytype_id() {
+    return $self->key->type;
+  }
+  const char *keytype_idstr() {
+    return id2str($self->pool, $self->key->type);
+  }
+  Id match_id() {
+     return $self->kv.id;
+  }
+  const char *match_idstr() {
+     return id2str($self->pool, $self->kv.id);
+  }
+  const char *match_str() {
+     return $self->kv.str;
+  }
+  int match_num() {
+     return $self->kv.num;
+  }
+  int match_num2() {
+     return $self->kv.num2;
+  }
+}
+
+
+%extend Pool_solvable_iterator {
+  Pool_solvable_iterator *__iter__() {
+    return $self;
+  }
+  %exception next {
+    $action
+    if (!result) {
+      PyErr_SetString(PyExc_StopIteration,"no more matches");
+      return NULL;
+    }
+  }
+  %newobject next;
+  xSolvable *next() {
+    Pool *pool = $self->pool;
+    xSolvable *s;
+    if ($self->id >= pool->nsolvables)
+      return 0;
+    while (++$self->id < pool->nsolvables)
+      if (pool->solvables[$self->id].repo)
+        return xSolvable_create(pool, $self->id);
+    return 0;
+  }
+  %newobject __getitem__;
+  xSolvable *__getitem__(Id key) {
+    Pool *pool = $self->pool;
+    if (key > 0 && key < pool->nsolvables && pool->solvables[key].repo)
+      return xSolvable_create(pool, key);
+    return 0;
+  }
+}
+
+%extend Pool_repo_iterator {
+  Pool_repo_iterator *__iter__() {
+    return $self;
+  }
+  %exception next {
+    $action
+    if (!result) {
+      PyErr_SetString(PyExc_StopIteration,"no more matches");
+      return NULL;
+    }
+  }
+  Repo *next() {
+    Pool *pool = $self->pool;
+    if ($self->id >= pool->nrepos + 1)
+      return 0;
+    while (++$self->id < pool->nrepos + 1) {
+      Repo *r = pool_id2repo(pool, $self->id);
+      if (r)
+        return r;
+    }
+    return 0;
+  }
+  Repo *__getitem__(Id key) {
+    Pool *pool = $self->pool;
+    if (key > 0 && key < pool->nrepos + 1)
+      return pool_id2repo(pool, key);
+    return 0;
+  }
+}
+
+%extend Repo_solvable_iterator {
+  Repo_solvable_iterator *__iter__() {
+    return $self;
+  }
+  %exception next {
+    $action
+    if (!result) {
+      PyErr_SetString(PyExc_StopIteration,"no more matches");
+      return NULL;
+    }
+  }
+  %newobject next;
+  xSolvable *next() {
+    Repo *repo = $self->repo;
+    Pool *pool = repo->pool;
+    xSolvable *s;
+    if (repo->start > 0 && $self->id < repo->start)
+      $self->id = repo->start - 1;
+    if ($self->id >= repo->end)
+      return 0;
+    while (++$self->id < repo->end)
+      if (pool->solvables[$self->id].repo == repo)
+        return xSolvable_create(pool, $self->id);
+    return 0;
+  }
+  %newobject __getitem__;
+  xSolvable *__getitem__(Id key) {
+    Repo *repo = $self->repo;
+    Pool *pool = repo->pool;
+    if (key > 0 && key < pool->nsolvables && pool->solvables[key].repo == repo)
+      return xSolvable_create(pool, key);
+    return 0;
+  }
+}
+
+%extend xSolvable {
+  const char *str() {
+    return solvid2str($self->pool, $self->id);
+  }
+  const char *lookup_str(Id keyname) {
+    return pool_lookup_str($self->pool, $self->id, keyname);
+  }
+  Id lookup_id(Id entry, Id keyname) {
+    return pool_lookup_id($self->pool, $self->id, keyname);
+  }
+  unsigned int lookup_num(Id keyname, unsigned int notfound = 0) {
+    return pool_lookup_num($self->pool, $self->id, keyname, notfound);
+  }
+  bool lookup_void(Id keyname) {
+    return pool_lookup_void($self->pool, $self->id, keyname);
+  }
+  SWIGCDATA lookup_bin_checksum(Id keyname, Id *OUTPUT) {
+    int l;
+    const unsigned char *b;
+    *OUTPUT = 0;
+    b = pool_lookup_bin_checksum($self->pool, $self->id, keyname, OUTPUT);
+    if (!b)
+      return cdata_void(0, 0);
+    return cdata_void((char *)b, sat_chksum_len(*OUTPUT));
+  }
+  const char *lookup_checksum(Id keyname, Id *OUTPUT) {
+    Id type = 0;
+    *OUTPUT = 0;
+    const char *b = pool_lookup_checksum($self->pool, $self->id, keyname, OUTPUT);
+    return b;
+  }
+  bool installable() {
+    return pool_installable($self->pool, pool_id2solvable($self->pool, $self->id));
+  }
+  bool isinstalled() {
+    Pool *pool = $self->pool;
+    return pool->installed && pool_id2solvable(pool, $self->id)->repo == pool->installed;
+  }
+
+  const char * const name;
+  %{
+    SWIGINTERN const char *xSolvable_name_get(xSolvable *xs) {
+      Pool *pool = xs->pool;
+      return id2str(pool, pool->solvables[xs->id].name);
+    }
+  %}
+  Id const nameid;
+  %{
+    SWIGINTERN Id xSolvable_nameid_get(xSolvable *xs) {
+      return xs->pool->solvables[xs->id].name;
+    }
+  %}
+  const char * const evr;
+  %{
+    SWIGINTERN const char *xSolvable_evr_get(xSolvable *xs) {
+      Pool *pool = xs->pool;
+      return id2str(pool, pool->solvables[xs->id].evr);
+    }
+  %}
+  Id const evrid;
+  %{
+    SWIGINTERN Id xSolvable_evrid_get(xSolvable *xs) {
+      return xs->pool->solvables[xs->id].evr;
+    }
+  %}
+  const char * const arch;
+  %{
+    SWIGINTERN const char *xSolvable_arch_get(xSolvable *xs) {
+      Pool *pool = xs->pool;
+      return id2str(pool, pool->solvables[xs->id].arch);
+    }
+  %}
+  Id const archid;
+  %{
+    SWIGINTERN Id xSolvable_archid_get(xSolvable *xs) {
+      return xs->pool->solvables[xs->id].arch;
+    }
+  %}
+  Repo * const repo;
+  %{
+    SWIGINTERN Repo *xSolvable_repo_get(xSolvable *xs) {
+      return xs->pool->solvables[xs->id].repo;
+    }
+  %}
+}
+
+%extend Problem {
+  Problem(Solver *solv, Id id) {
+    Problem *p;
+    p = sat_calloc(sizeof(*p), 1);
+    p->solv = solv;
+    p->id = id;
+    return p;
+  }
+  Id findproblemrule() {
+    return solver_findproblemrule($self->solv, $self->id);
+  }
+  Queue findallproblemrules(int unfiltered=0) {
+    Solver *solv = $self->solv;
+    Id probr;
+    int i, j;
+    Queue q;
+    queue_init(&q);
+    solver_findallproblemrules(solv, $self->id, &q);
+    if (!unfiltered)
+      {
+        for (i = j = 0; i < q.count; i++)
+          {
+            probr = q.elements[i];
+            if ((probr >= solv->updaterules && probr < solv->updaterules_end) || (probr >= solv->jobrules && probr < solv->jobrules_end))
+              continue;
+            q.elements[j++] = probr;
+          }
+        if (j)
+          queue_truncate(&q, j);
+      }
+    return q;
+  }
+}
+
+%extend Solver {
+  ~Solver() {
+    solver_free($self);
+  }
+  %pythoncode %{
+    def solve(self, jobs):
+      j = []
+      for job in jobs: j += [job.how, job.what]
+      nprob = self.solve_wrap(j)
+      return [ Problem(self, pid) for pid in range(1, nprob + 1) ]
+  %}
+  int solve_wrap(Queue jobs) {
+    solver_solve($self, &jobs);
+    return solver_problem_count($self);
+  }
+  %apply Id *OUTPUT { Id *source, Id *target, Id *dep };
+  int ruleinfo(Id ruleid, Id *source, Id *target, Id *dep) {
+    return solver_ruleinfo($self, ruleid, source, target, dep);
+  }
+}
index 8df2339..58e1bef 100644 (file)
@@ -2,7 +2,7 @@ SET(libsatsolverext_SRCS
     repo_content.c repo_deltainfoxml.c repo_helix.c repo_products.c
     repo_releasefile_products.c repo_repomdxml.c repo_rpmmd.c
     repo_susetags.c repo_updateinfoxml.c repo_write.c repo_zyppdb.c
-    repo_deb.c)
+    repo_deb.c sat_xfopen.c)
 IF ( NOT DEBIAN )
 SET(libsatsolverext_SRCS
     ${libsatsolverext_SRCS} pool_fileconflicts.c repo_rpmdb.c)
@@ -14,7 +14,7 @@ SET(libsatsolver_HEADERS
     pool_fileconflicts.h repo_content.h repo_deltainfoxml.h repo_helix.h repo_products.h
     repo_releasefile_products.h repo_repomdxml.h repo_rpmdb.h repo_rpmmd.h
     repo_susetags.h repo_updateinfoxml.h repo_write.h repo_zyppdb.h
-    tools_util.h repo_deb.h)
+    tools_util.h repo_deb.h sat_xfopen.h)
 
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
 
similarity index 73%
rename from tools/common_myfopen.h
rename to ext/sat_xfopen.c
index 0a52aa7..8333529 100644 (file)
@@ -5,8 +5,13 @@
  * for further information
  */
 
-#ifndef SATSOLVER_COMMON_MYFOPEN_H
-#define SATSOLVER_COMMON_MYFOPEN_H
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <string.h>
+#include <zlib.h>
+
+#include "sat_xfopen.h"
 
 static ssize_t cookie_gzread(void *cookie, char *buf, size_t nbytes)
 {
@@ -40,7 +45,7 @@ static FILE *mygzfopen(gzFile* gzf)
 }
 
 FILE *
-myfopen(const char *fn)
+sat_xfopen(const char *fn)
 {
   char *suf;
   gzFile *gzf;
@@ -56,4 +61,20 @@ myfopen(const char *fn)
   return mygzfopen(gzf);
 }
 
-#endif /* SATSOLVER_COMMON_MYFOPEN_H */
+FILE *
+sat_xfopen_fd(const char *fn, int fd)
+{
+  char *suf;
+  gzFile *gzf;
+
+  if (!fn)
+    return 0;
+  suf = strrchr(fn, '.');
+  if (!suf || strcmp(suf, ".gz") != 0)
+    return fdopen(fd, "r");
+  gzf = gzdopen(fd, "r");
+  if (!gzf)
+    return 0;
+  return mygzfopen(gzf);
+}
+
diff --git a/ext/sat_xfopen.h b/ext/sat_xfopen.h
new file mode 100644 (file)
index 0000000..826627d
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef SAT_XFOPEN_H
+#define SAT_XFOPEN_H
+
+extern FILE *sat_xfopen(const char *fn);
+extern FILE *sat_xfopen_fd(const char *fn, int fd);
+
+#endif
index 459b411..98c764f 100644 (file)
@@ -27,7 +27,7 @@
 #include "repo_deb.h"
 #endif
 #include "solver.h"
-#include "common_myfopen.h"
+#include "sat_xfopen.h"
 
 
 void
@@ -97,7 +97,7 @@ main(int argc, char **argv)
       l = strlen(argv[i]);
       if (!strcmp(argv[i], "-"))
        fp = stdin;
-      else if ((fp = myfopen(argv[i])) == 0)
+      else if ((fp = sat_xfopen(argv[i])) == 0)
        {
          perror(argv[i]);
          exit(1);
index 90b5ee0..82c612b 100644 (file)
@@ -26,7 +26,7 @@
 #include "solver.h"
 #include "solverdebug.h"
 
-#include "common_myfopen.h"
+#include "sat_xfopen.h"
 
 void
 showproblems(Solver *solv, Solvable *s, Queue *cand, Queue *badguys)
@@ -527,7 +527,7 @@ main(int argc, char **argv)
       l = strlen(argv[i]);
       if (!strcmp(argv[i], "-"))
         fp = stdin;
-      else if ((fp = myfopen(argv[i])) == 0)
+      else if ((fp = sat_xfopen(argv[i])) == 0)
         {
           perror(argv[i]);
           exit(1);
index 834f490..328af85 100644 (file)
@@ -20,7 +20,7 @@
 #include "repo.h"
 #include "repo_rpmmd.h"
 #include "common_write.h"
-#include "common_myfopen.h"
+#include "sat_xfopen.h"
 
 
 static void
@@ -80,7 +80,7 @@ main(int argc, char **argv)
       l = strlen(dir) + 128;
       fnp = sat_malloc(l+1);
       snprintf(fnp, l, "%s/primary.xml.gz", dir);
-      if (!(fp = myfopen(fnp)))
+      if (!(fp = sat_xfopen(fnp)))
        {
          perror(fnp);
          exit(1);
@@ -88,7 +88,7 @@ main(int argc, char **argv)
       repo_add_rpmmd(repo, fp, 0, flags);
       fclose(fp);
       snprintf(fnp, l, "%s/diskusagedata.xml.gz", dir);
-      if ((fp = myfopen(fnp)))
+      if ((fp = sat_xfopen(fnp)))
        {
          repo_add_rpmmd(repo, fp, 0, flags);
          fclose(fp);
@@ -100,7 +100,7 @@ main(int argc, char **argv)
              fprintf(stderr, "-l parameter too long\n");
              exit(1);
            }
-         while (!(fp = myfopen(fnp)))
+         while (!(fp = sat_xfopen(fnp)))
            {
              fprintf(stderr, "not opened %s\n", fnp);
              if (strlen(locale) > 2)
@@ -110,7 +110,7 @@ main(int argc, char **argv)
                      fprintf(stderr, "-l parameter too long\n");
                      exit(1);
                    }
-                 if ((fp = myfopen(fnp)))
+                 if ((fp = sat_xfopen(fnp)))
                    break;
                }
              perror(fnp);
index 9ba54db..2b926bb 100644 (file)
@@ -22,7 +22,7 @@
 #include "repo_susetags.h"
 #include "repo_content.h"
 #include "common_write.h"
-#include "common_myfopen.h"
+#include "sat_xfopen.h"
 
 static void
 usage(int status)
@@ -171,7 +171,7 @@ main(int argc, char **argv)
          if (!strcmp(fn, "packages") || !strcmp(fn, "packages.gz"))
            {
              sprintf(fnp, "%s/%s", descrdir, fn);
-             FILE *fp = myfopen(fnp);
+             FILE *fp = sat_xfopen(fnp);
              if (!fp)
                {
                  perror(fn);
@@ -183,7 +183,7 @@ main(int argc, char **argv)
          else if (!strcmp(fn, "packages.DU") || !strcmp(fn, "packages.DU.gz"))
            {
              sprintf(fnp, "%s/%s", descrdir, fn);
-             FILE *fp = myfopen(fnp);
+             FILE *fp = sat_xfopen(fnp);
              if (!fp)
                {
                  perror(fn);
@@ -196,7 +196,7 @@ main(int argc, char **argv)
            {
 #if 0
              sprintf(fnp, "%s/%s", descrdir, fn);
-             FILE *fp = myfopen(fnp);
+             FILE *fp = sat_xfopen(fnp);
              if (!fp)
                {
                  perror(fn);
@@ -224,7 +224,7 @@ main(int argc, char **argv)
                continue;
              strcpy(lang, p + 1);
              sprintf(fnp, "%s/%s", descrdir, fn);
-             FILE *fp = myfopen(fnp);
+             FILE *fp = sat_xfopen(fnp);
              if (!fp)
                {
                  perror(fn);