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