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