]> git.saurik.com Git - apt.git/blame_incremental - cmdline/apt-sortpkgs.cc
More tests
[apt.git] / cmdline / apt-sortpkgs.cc
... / ...
CommitLineData
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3// $Id: apt-sortpkgs.cc,v 1.2 2001/02/20 07:03:17 jgg Exp $
4/* ######################################################################
5
6 APT Sort Packages - Program to sort Package and Source files
7
8 This program is quite simple, it just sorts the package files by
9 package and sorts the fields inside by the internal APT sort order.
10 Input is taken from a named file and sent to stdout.
11
12 ##################################################################### */
13 /*}}}*/
14// Include Files /*{{{*/
15#include <apt-pkg/tagfile.h>
16#include <apt-pkg/error.h>
17#include <apt-pkg/configuration.h>
18#include <apt-pkg/cmndline.h>
19#include <apt-pkg/init.h>
20#include <apt-pkg/strutl.h>
21
22#include <config.h>
23#include <apti18n.h>
24
25#include <vector>
26#include <algorithm>
27
28#include <unistd.h>
29 /*}}}*/
30
31struct PkgName
32{
33 string Name;
34 string Ver;
35 string Arch;
36 unsigned long Offset;
37 unsigned long Length;
38
39 inline int Compare3(const PkgName &x) const
40 {
41 int A = stringcasecmp(Name,x.Name);
42 if (A == 0)
43 {
44 A = stringcasecmp(Ver,x.Ver);
45 if (A == 0)
46 A = stringcasecmp(Arch,x.Arch);
47 }
48 return A;
49 }
50
51 bool operator <(const PkgName &x) const {return Compare3(x) < 0;};
52 bool operator >(const PkgName &x) const {return Compare3(x) > 0;};
53 bool operator ==(const PkgName &x) const {return Compare3(x) == 0;};
54};
55
56// DoIt - Sort a single file /*{{{*/
57// ---------------------------------------------------------------------
58/* */
59bool DoIt(string InFile)
60{
61 FileFd Fd(InFile,FileFd::ReadOnly);
62 pkgTagFile Tags(&Fd);
63 if (_error->PendingError() == true)
64 return false;
65
66 // Parse.
67 vector<PkgName> List;
68 pkgTagSection Section;
69 unsigned long Largest = 0;
70 unsigned long Offset = Tags.Offset();
71 bool Source = _config->FindB("APT::SortPkgs::Source",false);
72 while (Tags.Step(Section) == true)
73 {
74 PkgName Tmp;
75
76 /* Fetch the name, auto-detecting if this is a source file or a
77 package file */
78 Tmp.Name = Section.FindS("Package");
79 Tmp.Ver = Section.FindS("Version");
80 Tmp.Arch = Section.FindS("Architecture");
81
82 if (Tmp.Name.empty() == true)
83 return _error->Error(_("Unknown package record!"));
84
85 Tmp.Offset = Offset;
86 Tmp.Length = Section.size();
87 if (Largest < Tmp.Length)
88 Largest = Tmp.Length;
89
90 List.push_back(Tmp);
91
92 Offset = Tags.Offset();
93 }
94 if (_error->PendingError() == true)
95 return false;
96
97 // Sort it
98 sort(List.begin(),List.end());
99
100 const char **Order = TFRewritePackageOrder;
101 if (Source == true)
102 Order = TFRewriteSourceOrder;
103
104 // Emit
105 unsigned char *Buffer = new unsigned char[Largest+1];
106 for (vector<PkgName>::iterator I = List.begin(); I != List.end(); I++)
107 {
108 // Read in the Record.
109 if (Fd.Seek(I->Offset) == false || Fd.Read(Buffer,I->Length) == false)
110 {
111 delete [] Buffer;
112 return false;
113 }
114
115 Buffer[I->Length] = '\n';
116 if (Section.Scan((char *)Buffer,I->Length+1) == false)
117 {
118 delete [] Buffer;
119 return _error->Error("Internal error, failed to scan buffer");
120 }
121
122 // Sort the section
123 if (TFRewrite(stdout,Section,Order,0) == false)
124 {
125 delete [] Buffer;
126 return _error->Error("Internal error, failed to sort fields");
127 }
128
129 fputc('\n',stdout);
130 }
131
132 delete [] Buffer;
133 return true;
134}
135 /*}}}*/
136// ShowHelp - Show the help text /*{{{*/
137// ---------------------------------------------------------------------
138/* */
139int ShowHelp()
140{
141 ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
142 COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
143 if (_config->FindB("version") == true)
144 return 0;
145
146 cout <<
147 _("Usage: apt-sortpkgs [options] file1 [file2 ...]\n"
148 "\n"
149 "apt-sortpkgs is a simple tool to sort package files. The -s option is used\n"
150 "to indicate what kind of file it is.\n"
151 "\n"
152 "Options:\n"
153 " -h This help text\n"
154 " -s Use source file sorting\n"
155 " -c=? Read this configuration file\n"
156 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n");
157
158 return 0;
159}
160 /*}}}*/
161
162int main(unsigned int argc,const char *argv[])
163{
164 CommandLine::Args Args[] = {
165 {'h',"help","help",0},
166 {'v',"version","version",0},
167 {'s',"source","APT::SortPkgs::Source",0},
168 {'c',"config-file",0,CommandLine::ConfigFile},
169 {'o',"option",0,CommandLine::ArbItem},
170 {0,0,0,0}};
171
172 // Parse the command line and initialize the package library
173 CommandLine CmdL(Args,_config);
174 if (pkgInitConfig(*_config) == false ||
175 CmdL.Parse(argc,argv) == false ||
176 pkgInitSystem(*_config,_system) == false)
177 {
178 _error->DumpErrors();
179 return 100;
180 }
181
182 // See if the help should be shown
183 if (_config->FindB("help") == true ||
184 CmdL.FileSize() == 0)
185 return ShowHelp();
186
187 // Match the operation
188 for (unsigned int I = 0; I != CmdL.FileSize(); I++)
189 if (DoIt(CmdL.FileList[I]) == false)
190 break;
191
192 // Print any errors or warnings found during parsing
193 if (_error->empty() == false)
194 {
195 bool Errors = _error->PendingError();
196 _error->DumpErrors();
197 return Errors == true?100:0;
198 }
199
200 return 0;
201}