File: generate-install-list

package info (click to toggle)
emacsen-common 1.4.15
  • links: PTS
  • area: main
  • in suites: woody
  • size: 92 kB
  • ctags: 32
  • sloc: perl: 194; lisp: 111; sh: 91; makefile: 75
file content (142 lines) | stat: -rwxr-xr-x 3,944 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/perl -w

use strict;

# depends on: dpkg, tsort, perl

# This script should be handed a list of add-on packages on stdin, and
# it will sort them according to their dependencies.  It will also add
# in other add-on packages that aren't mentioned, but are needed.

my $lib_dir = "/usr/lib/emacsen-common";
my $var_dir = "/var/lib/emacsen-common";
my $installed_add_on_pkgs = undef;

sub cwd {
  my $result = `pwd`;
  chomp $result;
  return $result;
}

sub installed_add_on_packages_list {
  # Caches value for future use...

  if(! defined(@$installed_add_on_pkgs)) {
    my $oldir = cwd();    
    chdir($lib_dir . "/packages/install/") or die "couldn't chdir";
    @$installed_add_on_pkgs = glob("*");
    chdir($oldir);
  }
  return $installed_add_on_pkgs;
}

sub get_package_status {
  my($pkg) = @_;
  my $status = `dpkg --status $pkg`;
  $status =~ s/\n\s+//gmo; # handle any continuation lines...

  return $status;
}

sub filter_depends {
  my($depends_string, $installed_add_ons) = @_;

  # Filter out all the "noise" (version number dependencies, etc)
  # and handle or deps too "Depends: foo, bar | baz" 
  my @relevant_depends = split(/[,|]/, $depends_string);
  @relevant_depends = map { /\s*(\S+)/o; $1; } @relevant_depends;

  # Filter out all non-add-on packages.
  @relevant_depends = grep {
    my $candidate = $_;
    grep { $_ eq $candidate } @$installed_add_ons;
  } @relevant_depends;
  
  return @relevant_depends;
}

sub generate_relevant_tsort_dependencies {
  my($pkglist, $installed_add_ons, $progress_hash) = @_;

  # Make a copy because we're going to mangle it.
  my @listcopy = @$pkglist;

  shift @_;
  return(generate_relevant_tsort_dependencies_internals(\@listcopy, @_));
}

sub generate_relevant_tsort_dependencies_internals {
  my($pkglist, $installed_add_ons, $progress_hash) = @_;

  # print "GRD: " . join(" ", @$pkglist) . "\n";
  
  my $pkg = shift @$pkglist;

  if(!$pkg || $$progress_hash{$pkg}) {
    return ();
  } else {
    my $status = get_package_status($pkg);
    $status =~ /^Depends:\s+(.*)/mo;
    my $depends = $1; $depends = "" if ! $depends;
    my @relevant_depends = filter_depends($depends, $installed_add_ons);
    my $newpkglist = [@$pkglist, @relevant_depends];

    $$progress_hash{$pkg} = 1;

    # pkg is in twice so we don't have to worry about package with no
    # relevant dependencies.  tsort can't handle that.

    my @tsort_strings = "$pkg $pkg\n"; 

    map { push @tsort_strings, "$_ $pkg\n"; } @relevant_depends;
    
    return (@tsort_strings,
            generate_relevant_tsort_dependencies_internals($newpkglist,
                                                           $installed_add_ons,
                                                           $progress_hash));
  }
}

sub reorder_add_on_packages {
  my($pkglist, $installed_add_ons) = @_;

  my @depends = generate_relevant_tsort_dependencies($pkglist,
                                                     $installed_add_ons,
                                                     {}
                                                     );

  my $pid = open(TSORT, "-|");
  die "Couldn't fork for tsort: $!" unless defined($pid);

  # What a strange idiom...
  if($pid == 0) {
    my $sub_pid = open(IN, "|-");
    die "Couldn't sub-fork for tsort: $!" unless defined($sub_pid);
    if($sub_pid == 0) {
      exec 'tsort' or die "Couldn't run tsort: $!";
    }
    print IN @depends;
    exit 0;
  }
  my @ordered_pkgs = <TSORT>;
  chomp @ordered_pkgs;
  
  return @ordered_pkgs
}

sub generate_add_on_install_list {
  my($packages_to_sort) = @_;

  my @sorted_pkgs = reorder_add_on_packages($packages_to_sort,
                                            installed_add_on_packages_list());
  
  return(@sorted_pkgs);
}

# Test code
# my @input_packages = <STDIN>;
# my @result = generate_add_on_install_list(@input_packages);
# print "  " . join("\n  ", @result);

# To make require happy...
1;