Join with aliencode
[ntk/apt.git] / cmdline / apt-sortpkgs.cc
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
31 struct 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 /* */
59 bool 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 /* */
139 int 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
162 int 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 }