]> git.saurik.com Git - apt.git/blob - cmdline/apt-sortpkgs.cc
93aa5a76b64af90fc03851aceba793c9e0995079
[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 #include <apt-pkg/fileutl.h>
24 #include <apt-pkg/pkgsystem.h>
25
26 #include <apt-private/private-cmndline.h>
27 #include <apt-private/private-main.h>
28
29 #include <vector>
30 #include <algorithm>
31 #include <stdio.h>
32 #include <iostream>
33 #include <string>
34 #include <memory>
35
36 #include <apti18n.h>
37 /*}}}*/
38
39 using namespace std;
40
41 struct PkgName /*{{{*/
42 {
43 string Name;
44 string Ver;
45 string Arch;
46 unsigned long Offset;
47 unsigned long Length;
48
49 inline int Compare3(const PkgName &x) const
50 {
51 int A = stringcasecmp(Name,x.Name);
52 if (A == 0)
53 {
54 A = stringcasecmp(Ver,x.Ver);
55 if (A == 0)
56 A = stringcasecmp(Arch,x.Arch);
57 }
58 return A;
59 }
60
61 bool operator <(const PkgName &x) const {return Compare3(x) < 0;};
62 bool operator >(const PkgName &x) const {return Compare3(x) > 0;};
63 bool operator ==(const PkgName &x) const {return Compare3(x) == 0;};
64 };
65 /*}}}*/
66 // DoIt - Sort a single file /*{{{*/
67 // ---------------------------------------------------------------------
68 /* */
69 static bool DoIt(string InFile)
70 {
71 FileFd Fd(InFile,FileFd::ReadOnly);
72 pkgTagFile Tags(&Fd);
73 if (_error->PendingError() == true)
74 return false;
75
76 // Parse.
77 vector<PkgName> List;
78 pkgTagSection Section;
79 unsigned long Largest = 0;
80 unsigned long Offset = Tags.Offset();
81 bool Source = _config->FindB("APT::SortPkgs::Source",false);
82 while (Tags.Step(Section) == true)
83 {
84 PkgName Tmp;
85
86 /* Fetch the name, auto-detecting if this is a source file or a
87 package file */
88 Tmp.Name = Section.FindS("Package");
89 Tmp.Ver = Section.FindS("Version");
90 Tmp.Arch = Section.FindS("Architecture");
91
92 if (Tmp.Name.empty() == true)
93 return _error->Error(_("Unknown package record!"));
94
95 Tmp.Offset = Offset;
96 Tmp.Length = Section.size();
97 if (Largest < Tmp.Length)
98 Largest = Tmp.Length;
99
100 List.push_back(Tmp);
101
102 Offset = Tags.Offset();
103 }
104 if (_error->PendingError() == true)
105 return false;
106
107 // Sort it
108 sort(List.begin(),List.end());
109
110 const char **Order = TFRewritePackageOrder;
111 if (Source == true)
112 Order = TFRewriteSourceOrder;
113
114 // Emit
115 FileFd stdoutfd;
116 stdoutfd.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly, false);
117 auto const Buffer = std::unique_ptr<unsigned char[]>(new unsigned char[Largest+1]);
118 for (vector<PkgName>::iterator I = List.begin(); I != List.end(); ++I)
119 {
120 // Read in the Record.
121 if (Fd.Seek(I->Offset) == false || Fd.Read(Buffer.get(),I->Length) == false)
122 return false;
123
124 Buffer[I->Length] = '\n';
125 if (Section.Scan((char *)Buffer.get(),I->Length+1) == false)
126 return _error->Error("Internal error, failed to scan buffer");
127
128 // Sort the section
129 if (Section.Write(stdoutfd, Order) == false || stdoutfd.Write("\n", 1) == false)
130 return _error->Error("Internal error, failed to sort fields");
131 }
132 return true;
133 }
134 /*}}}*/
135 // ShowHelp - Show the help text /*{{{*/
136 // ---------------------------------------------------------------------
137 /* */
138 static bool ShowHelp(CommandLine &, CommandLine::DispatchWithHelp const *)
139 {
140 ioprintf(std::cout, "%s %s (%s)\n", PACKAGE, PACKAGE_VERSION, COMMON_ARCH);
141 if (_config->FindB("version") == true)
142 return true;
143
144 cout <<
145 _("Usage: apt-sortpkgs [options] file1 [file2 ...]\n"
146 "\n"
147 "apt-sortpkgs is a simple tool to sort package files. The -s option is used\n"
148 "to indicate what kind of file it is.\n"
149 "\n"
150 "Options:\n"
151 " -h This help text\n"
152 " -s Use source file sorting\n"
153 " -c=? Read this configuration file\n"
154 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n");
155
156 return true;
157 }
158 /*}}}*/
159 int main(int argc,const char *argv[]) /*{{{*/
160 {
161 InitLocale();
162
163 // Parse the command line and initialize the package library
164 CommandLine::DispatchWithHelp Cmds[] = {{nullptr, nullptr, nullptr}};
165 CommandLine CmdL;
166 ParseCommandLine(CmdL, Cmds, "apt-sortpkgs", &_config, &_system, argc, argv, ShowHelp);
167
168 // Match the operation
169 for (unsigned int I = 0; I != CmdL.FileSize(); I++)
170 if (DoIt(CmdL.FileList[I]) == false)
171 break;
172
173 return DispatchCommandLine(CmdL, nullptr);
174 }
175 /*}}}*/