octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: packaging system


From: Søren Hauberg
Subject: Re: packaging system
Date: Sun, 26 Jun 2005 23:31:04 +0200
User-agent: Mozilla Thunderbird 1.0.2 (X11/20050404)

David Bateman wrote:
Hi,
I'm back from my short vacation and I've had a look at your code. I've altered a bit in the way descriptions are represented (the change was from a struct containing cells to a cell containing structs) and I've adapted your code to this change (although I've made a dirty hack because I was lazy).

The current code supports
*) the installation of multible packages with one function call (i.e. the package files are given as a cell array).
*) Dependency checking at uninstall time
*) Circular dependecies (I think)

It does have one problem. If multible packages are installed with one function call the order of the installation is sortof random. So if package A depends on package B at install time, package A might be installed before package B, which would yield an error. Am I making sense?

As always the source is at http://hauberg.org/octave-package/package.tgz

/Søren

Also, only checks against the installed packages are performed.. What I see as an extention is to create a complete dependency table of all of the installed packages, with a function like

function dependency_table = installed_dependencies (prefix, installed_packages)
 count = 0;
 for i = 1:length(installed_packages.name)
   desc = get_description ([prefix, installed_packages.name{i}]);
   verify_description (desc);
   for j = 1:length(desc.keywords)
     if (strcmp(desc.keywords{j}, "DEPENDS"))
        deps = parse_dependencies ( desc.values{i});
        if (iscell (deps))
          for k = 1:length(deps)
             count++;
             dependency_table.name{count} = installed_packages.name{i};
dependency_table.version{count} = installed_packages.version{i};
             dependency_table.package{count} = deps.package{k};
             dependency_table.operator{count} = deps.operator{k};
             dependency_table.dversion{count} = deps.version{k};
        endif
     endif
   endfor
 endfor
endfunction

function pdep = parse_dependencies (deps)
   deps = split_by(tolower(deps), ",");

   if (length(deps) < 1)
      pdeps = false;
      return;
   endif

   ## For each dependency
   for i = 1:length(deps)
       dep = deps{i};
       lpar = find(dep == "(");
       rpar = find(dep == ")");
       ## Does the dependency specify a version
       ## Example: package(>= version)
       if (length(lpar) == 1 && length(rpar) == 1)
           package = tolower(strip(dep(1:lpar-1)));
           sub = dep( lpar(1)+1:rpar(1)-1 );
           parts = split_by(sub, " ");
           idx = [];
           for r = 1:size(parts,1)
               if (length(parts{r}) > 0)
                   idx(end+1) = r;
               endif
           endfor
                      if (length(idx) != 2)
error(["There's something wrong with the DESCRIPTION file. " ...
                      "The dependency %s has the wrong syntax.\n"], dep);
           endif
           operator = parts{idx(1)};
           version  = fix_version(parts{idx(2)});
                  ## If no version is specified for the dependcy
       ## we say that the version should be greater than
       ## or equal to 0.0.0
       else
           pdep.package{i} = tolower(strip(dep));
           pdep.operator{i} = ">=";
           pdep.version{i}  = "0.0.0";
       endif
    endfor
endfunction

then have three other function, one to remove a package, one to add a package to the table and another to validate the dependency table, like

function new_table = delete_dependency (table, name)
  count = 0;
  for i = 1:length(table.name)
     if (table.name{i} != name)
        count++;
        new_table.name{count} = table.name{i};
        new_table.version{count} = table.version{i};
        new_table.package{count} = table.package{i};
        new_table.operator{count} = table.operator{i};
        new_table.dversion{count} = table.dversion{i};
      endif
   endfor

   if (count == 0)
     new_table = false;
   endif
endfunction

function table = add_dependency (table, name, version, desc)
   count = length (table.name);
   for j = 1:length(desc.keywords)
     if (strcmp(desc.keywords{j}, "DEPENDS"))
        deps = parse_dependencies ( desc.values{i});
        if (iscell (deps))
          for k = 1:length(deps)
            count++;
            table.name{count} = name;
            table.version{count} = version;
            table.package{count} = deps.package{k};
            table.operator{count} = deps.operator{k};
            table.dversion{count} = deps.version{k};
          endfor
        endif
     endif
  endfor
endfunction

function ret = check_dependency_table (table, packages)
  for i = 1:length(table.name)
     name = table.name{i};
     version = table.version{i};
     package = table.package{i};
     operator = table.operator{i};
     dversion = table.dversion{i};
     found = false;
     for j = 1:length(packages.name)
        if (strcmp (packages.name{j}, package) &&
            (compare_versions(packages.version{j}, dversion, operator)))
          found = true;
          break;           endif
     endfor
     if (! found)
        error ("missing dependency");
     endif
  endfor
endfunction

where packages in the function check_dependency_table is the list of packages that will be installed after the current operation is finished, and has the same form as installed_packages in the existing code.

Ok, none of the above code is checked as I wrote it straight into my e-mail client, but at least it gives an idea of what I'm thinking about.. Including allowing cell-arrays to install/uninstall, it addresses the issues of circular dependencies and dependencies on uninstalling...

Cheers
D.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]