- implement package(version) changelog operation in lua interface
[apt.git] / apt-pkg / luaiface.cc
1 // CNC:2003-03-15
2 // -*- mode: c++; mode: fold -*-
3 // Description                                                          /*{{{*/
4 // $Id: repository.cc,v 1.4 2002/07/29 18:13:52 niemeyer Exp $
5 /* ######################################################################
6
7    Lua interface system.
8    
9    ##################################################################### */
10                                                                         /*}}}*/
11 #ifdef __GNUG__
12 #pragma implementation "apt-pkg/luaiface.h"
13 #endif       
14
15 #include <config.h>
16
17 #ifdef APT_WITH_LUA
18
19 extern "C" {
20 #include "lua.h"
21 #include "lualib.h"
22 #include "lauxlib.h"
23 #include "lposix.h"
24 #include "lrexlib.h"
25 #include "linit.h"
26 }
27
28 #include <apt-pkg/depcache.h>
29 #include <apt-pkg/configuration.h>
30 #include <apt-pkg/algorithms.h>
31 #include <apt-pkg/error.h>
32 #include <apt-pkg/pkgrecords.h>
33 #include <apt-pkg/sptr.h>
34 #include <apt-pkg/version.h>
35 #include <apt-pkg/pkgsystem.h>
36
37 #include <apt-pkg/luaiface.h>
38
39 #include <apti18n.h>
40
41 #include <limits.h>
42 #include <unistd.h>
43 #include <sys/types.h>
44 #include <assert.h>
45
46 #define pushudata(ctype, value) \
47    do { \
48       ctype *_tmp = (ctype *) lua_newuserdata(L, sizeof(ctype)); \
49       *_tmp = (ctype) value; \
50       luaL_getmetatable(L, #ctype); \
51       lua_setmetatable(L, -2); \
52    } while (0)
53
54 #define checkudata(ctype, target, n) \
55    do { \
56       ctype *_tmp = (ctype *) luaL_checkudata(L, n, #ctype); \
57       if (_tmp != NULL) \
58          target = *_tmp; \
59       else \
60          target = NULL; \
61    } while (0)
62
63 Lua *_GetLuaObj()
64 {
65    static Lua *Obj = new Lua;
66    return Obj;
67 }
68
69 static int luaopen_apt(lua_State *L);
70
71 static int AptLua_vercomp(lua_State *L);
72 static int AptLua_pkgcomp(lua_State *L);
73
74 #define CACHE_KEY "ChunkCache"
75
76 Lua::Lua()
77       : DepCache(0), Cache(0), CacheControl(0), Fix(0), DontFix(0)
78 {
79    _config->CndSet("Dir::Bin::scripts", PKGDATADIR "/scripts");
80
81    const luaL_reg lualibs[] = {
82       {"base", luaopen_base},
83       {"table", luaopen_table},
84       {"io", luaopen_io},
85       {"string", luaopen_string},
86       {"math", luaopen_math},
87       {"debug", luaopen_debug},
88       {"loadlib", luaopen_loadlib},
89       {"posix", luaopen_posix},
90       {"rex", luaopen_rex},
91       {"init", luaopen_init},
92       {"apt", luaopen_apt},
93       {NULL, NULL}
94    };
95    L = lua_open();
96    const luaL_reg *lib = lualibs;
97    for (; lib->name; lib++) {
98       lib->func(L);  /* open library */
99       lua_settop(L, 0);  /* discard any results */
100    }
101    luaL_newmetatable(L, "pkgCache::Package*");
102    lua_pushstring(L, "__eq");
103    lua_pushcfunction(L, AptLua_pkgcomp);
104    lua_settable(L, -3);
105    luaL_newmetatable(L, "pkgCache::Version*");
106    lua_pushstring(L, "__eq");
107    lua_pushcfunction(L, AptLua_vercomp);
108    lua_settable(L, -3);
109    lua_pop(L, 2);
110    lua_pushstring(L, CACHE_KEY);
111    lua_newtable(L);
112    lua_rawset(L, LUA_REGISTRYINDEX);
113 }
114
115 Lua::~Lua()
116 {
117    if (CacheControl)
118       CacheControl->Close();
119    lua_close(L);
120 }
121
122 bool Lua::HasScripts(const char *ConfListKey)
123 {
124    const Configuration::Item *Top = _config->Tree(ConfListKey);
125    if (Top != 0 && Top->Child != 0)
126       return true;
127    return false;
128 }
129
130 bool Lua::RunScripts(const char *ConfListKey, bool CacheChunks)
131 {
132    lua_pushstring(L, CACHE_KEY);
133    lua_rawget(L, LUA_REGISTRYINDEX);
134    assert(lua_istable(L, -1));
135
136    int CacheIndex = lua_gettop(L);
137
138    lua_pushstring(L, ConfListKey);
139    lua_rawget(L, CacheIndex);
140
141    if (lua_isnil(L, -1)) {
142       string File, Dir = _config->FindDir("Dir::Bin::scripts", "");
143       lua_pop(L, 1);
144       lua_newtable(L);
145       int Count = 0;
146       const Configuration::Item *Top = _config->Tree(ConfListKey);
147       for (Top = (Top == 0?0:Top->Child); Top != 0; Top = Top->Next) {
148          const string &Value = Top->Value;
149          if (Value.empty() == true)
150             continue;
151          if (Value == "interactive") {
152             lua_pushstring(L, "script_slot");
153             lua_pushstring(L, ConfListKey);
154             lua_rawset(L, LUA_GLOBALSINDEX);
155
156             RunInteractive(ConfListKey);
157
158             lua_pushstring(L, "script_slot");
159             lua_pushnil(L);
160             lua_rawset(L, LUA_GLOBALSINDEX);
161             continue;
162          }
163          if (Value[0] == '.' || Value[0] == '/') {
164             if (FileExists(Value) == true)
165                File = Value;
166             else
167                continue;
168          } else {
169             File = Dir+Value;
170             if (FileExists(File) == false)
171                continue;
172          }
173          if (luaL_loadfile(L, File.c_str()) != 0) {
174             _error->Warning(_("Error loading script: %s"),
175                             lua_tostring(L, -1));
176             lua_pop(L, 1);
177          }
178          lua_rawseti(L, -2, ++Count);
179       }
180       if (Count == 0) {
181          lua_pop(L, 2); // Script table and cache table.
182          return false;
183       }
184       if (CacheChunks == true) {
185          lua_pushstring(L, ConfListKey);
186          lua_pushvalue(L, -2);
187          lua_rawset(L, CacheIndex);
188       }
189    }
190
191    lua_pushstring(L, "script_slot");
192    lua_pushstring(L, ConfListKey);
193    lua_rawset(L, LUA_GLOBALSINDEX);
194
195    InternalRunScript();
196
197    lua_pushstring(L, "script_slot");
198    lua_pushnil(L);
199    lua_rawset(L, LUA_GLOBALSINDEX);
200
201    lua_pop(L, 1);
202
203    return true;
204 }
205
206 bool Lua::RunScript(const char *Script, const char *ChunkCacheKey)
207 {
208    lua_pushstring(L, CACHE_KEY);
209    lua_rawget(L, LUA_REGISTRYINDEX);
210    assert(lua_istable(L, -1));
211
212    int CacheIndex = lua_gettop(L);
213
214    if (Script == NULL || *Script == '\0')
215       return false;
216    
217    bool Cached = false;
218    if (ChunkCacheKey) {
219       lua_pushstring(L, ChunkCacheKey);
220       lua_rawget(L, 1);
221       if (!lua_isnil(L, -1))
222          Cached = true;
223       else
224          lua_pop(L, 1);
225    }
226
227    if (Cached == false) {
228       if (luaL_loadbuffer(L, Script, strlen(Script), "<lua>") != 0) {
229          _error->Warning(_("Error loading script: %s"),
230                          lua_tostring(L, -1));
231          lua_pop(L, 2); // Error and cache table
232          assert(lua_gettop(L) == 0);
233          return false;
234       }
235
236       if (ChunkCacheKey) {
237          lua_pushstring(L, ChunkCacheKey);
238          lua_pushvalue(L, -2);
239          lua_rawset(L, CacheIndex);
240       }
241    }
242
243    InternalRunScript();
244
245    lua_pop(L, 1);
246
247    return true;
248 }
249
250 void Lua::InternalRunScript()
251 {
252    // Script or script list must be at the top, and will be poped.
253    if (lua_istable(L, -1)) {
254       int t = lua_gettop(L);
255       lua_pushnil(L);
256       while (lua_next(L, t)) {
257          if (lua_pcall(L, 0, 0, 0) != 0) {
258             _error->Warning(_("Error running script: %s"),
259                             lua_tostring(L, -1));
260             lua_remove(L, -1);
261          }
262       }
263       lua_pop(L, 1);
264    } else {
265       if (lua_pcall(L, 0, 0, 0) != 0) {
266          _error->Warning(_("Error running script: %s"),
267                          lua_tostring(L, -1));
268          lua_remove(L, -1);
269       }
270    }
271 }
272
273 /* From lua.c */
274 static int AptAux_readline(lua_State *l, const char *prompt) {
275    static char buffer[1024];
276    if (prompt) {
277       fputs(prompt, stdout);
278       fflush(stdout);
279    }
280    if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
281       return 0;  /* read fails */
282    } else {
283       lua_pushstring(l, buffer);
284       return 1;
285    }
286 }
287
288 /* Based on lua.c */
289 void Lua::RunInteractive(const char *PlaceHint)
290 {
291    cout << endl
292         << "APT Interactive " << LUA_VERSION << " Interpreter" << endl;
293    if (PlaceHint)
294         cout << "[" << PlaceHint << "]" << endl;
295    for (;;) {
296       if (AptAux_readline(L, "> ") == 0)
297          break;
298       if (lua_tostring(L, -1)[0] == '=') {
299          lua_pushfstring(L, "print(%s)", lua_tostring(L, -1)+1);
300          lua_remove(L, -2);
301       }
302       int rc = 0;
303       for (;;) {
304          rc = luaL_loadbuffer(L, lua_tostring(L, -1),
305                               lua_strlen(L, -1), "<lua>");
306          if (rc == LUA_ERRSYNTAX &&
307              strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
308             if (AptAux_readline(L, ">> ") == 0)
309                break;
310             lua_remove(L, -2); // Remove error
311             lua_concat(L, 2);
312             continue;
313          }
314          break;
315       }
316       if (rc == 0)
317          rc = lua_pcall(L, 0, 0, 0);
318       if (rc != 0) {
319          fprintf(stderr, "%s\n", lua_tostring(L, -1));
320          lua_pop(L, 1);
321       }
322       lua_pop(L, 1); // Remove line
323    }
324    fputs("\n", stdout);
325 }
326
327 void Lua::ResetScript(const char *ChunkCacheKey)
328 {
329    lua_pushstring(L, ChunkCacheKey);
330    lua_pushnil(L);
331    lua_rawset(L, 1);
332 }
333
334 void Lua::SetGlobal(const char *Name)
335 {
336    lua_pushstring(L, Name);
337    lua_pushnil(L);
338    lua_rawset(L, LUA_GLOBALSINDEX);
339    Globals.push_back(Name);
340 }
341
342 void Lua::SetGlobal(const char *Name, const char *Value)
343 {
344    if (Value != NULL) {
345       lua_pushstring(L, Name);
346       lua_pushstring(L, Value);
347       lua_rawset(L, LUA_GLOBALSINDEX);
348    }
349    Globals.push_back(Name);
350 }
351
352 void Lua::SetGlobal(const char *Name, pkgCache::Package *Value)
353 {
354    if (Value != NULL) {
355       lua_pushstring(L, Name);
356       pushudata(pkgCache::Package*, Value);
357       lua_rawset(L, LUA_GLOBALSINDEX);
358    }
359    Globals.push_back(Name);
360 }
361
362 void Lua::SetGlobal(const char *Name, const char **Value, int Total)
363 {
364    lua_pushstring(L, Name);
365    lua_newtable(L);
366    if (Total == -1)
367       Total = INT_MAX;
368    for (int i=0; i != Total && Value[i] != NULL; i++) {
369       lua_pushstring(L, Value[i]);
370       lua_rawseti(L, -2, i+1);
371    }
372    lua_rawset(L, LUA_GLOBALSINDEX);
373    Globals.push_back(Name);
374 }
375
376 void Lua::SetGlobal(const char *Name, vector<const char *> &Value,
377                     int Total)
378 {
379    lua_pushstring(L, Name);
380    lua_newtable(L);
381    if (Total == -1 || (size_t)Total > Value.size())
382       Total = Value.size();
383    for (int i=0; i != Total && Value[i] != NULL; i++) {
384       lua_pushstring(L, Value[i]);
385       lua_rawseti(L, -2, i+1);
386    }
387    lua_rawset(L, LUA_GLOBALSINDEX);
388    Globals.push_back(Name);
389 }
390
391 void Lua::SetGlobal(const char *Name, vector<string> &Value,
392                     int Total)
393 {
394    lua_pushstring(L, Name);
395    lua_newtable(L);
396    if (Total == -1 || (size_t)Total > Value.size())
397       Total = Value.size();
398    for (int i=0; i != Total; i++) {
399       lua_pushstring(L, Value[i].c_str());
400       lua_rawseti(L, -2, i+1);
401    }
402    lua_rawset(L, LUA_GLOBALSINDEX);
403    Globals.push_back(Name);
404 }
405
406 void Lua::SetGlobal(const char *Name, vector<pkgCache::Package*> &Value,
407                     int Total)
408 {
409    lua_pushstring(L, Name);
410    lua_newtable(L);
411    if (Total == -1 || (size_t)Total > Value.size())
412       Total = Value.size();
413    for (int i=0; i != Total && Value[i] != NULL; i++) {
414       pushudata(pkgCache::Package*, Value[i]);
415       lua_rawseti(L, -2, i+1);
416    }
417    lua_rawset(L, LUA_GLOBALSINDEX);
418    Globals.push_back(Name);
419 }
420
421 void Lua::SetGlobal(const char *Name, bool Value)
422 {
423    lua_pushstring(L, Name);
424    lua_pushboolean(L, Value);
425    lua_rawset(L, LUA_GLOBALSINDEX);
426    Globals.push_back(Name);
427 }
428
429 void Lua::SetGlobal(const char *Name, double Value)
430 {
431    lua_pushstring(L, Name);
432    lua_pushnumber(L, Value);
433    lua_rawset(L, LUA_GLOBALSINDEX);
434    Globals.push_back(Name);
435 }
436
437 void Lua::SetGlobal(const char *Name, void *Value)
438 {
439    if (Value != NULL) {
440       lua_pushstring(L, Name);
441       lua_pushlightuserdata(L, Value);
442       lua_rawset(L, LUA_GLOBALSINDEX);
443    }
444    Globals.push_back(Name);
445 }
446
447 void Lua::SetGlobal(const char *Name, lua_CFunction Value)
448 {
449    lua_pushstring(L, Name);
450    lua_pushcfunction(L, Value);
451    lua_rawset(L, LUA_GLOBALSINDEX);
452    Globals.push_back(Name);
453 }
454
455 void Lua::ResetGlobals()
456 {
457    if (Globals.empty() == false) {
458       for (vector<string>::const_iterator I = Globals.begin();
459            I != Globals.end(); I++) {
460          lua_pushstring(L, I->c_str());
461          lua_pushnil(L);
462          lua_rawset(L, LUA_GLOBALSINDEX);
463       }
464       Globals.clear();
465    }
466 }
467
468 const char *Lua::GetGlobalStr(const char *Name)
469 {
470    lua_pushstring(L, Name);
471    lua_rawget(L, LUA_GLOBALSINDEX);
472    const char *Ret = NULL;
473    if (lua_isstring(L, -1))
474       Ret = lua_tostring(L, -1);
475    lua_remove(L, -1);
476    return Ret;
477 }
478
479 vector<string> Lua::GetGlobalStrList(const char *Name)
480 {
481    vector<string> Ret;
482    lua_pushstring(L, Name);
483    lua_rawget(L, LUA_GLOBALSINDEX);
484    int t = lua_gettop(L);
485    if (lua_istable(L, t)) {
486       lua_pushnil(L);
487       while (lua_next(L, t) != 0) {
488          if (lua_isstring(L, -1))
489             Ret.push_back(lua_tostring(L, -1));
490          lua_pop(L, 1);
491       }
492    }
493    lua_remove(L, -1);
494    return Ret;
495 }
496
497 double Lua::GetGlobalNum(const char *Name)
498 {
499    lua_pushstring(L, Name);
500    lua_rawget(L, LUA_GLOBALSINDEX);
501    double Ret = 0;
502    if (lua_isnumber(L, -1))
503       Ret = lua_tonumber(L, -1);
504    lua_remove(L, -1);
505    return Ret;
506 }
507
508 bool Lua::GetGlobalBool(const char *Name)
509 {
510    lua_pushstring(L, Name);
511    lua_rawget(L, LUA_GLOBALSINDEX);
512    bool Ret = lua_toboolean(L, -1);
513    lua_remove(L, -1);
514    return Ret;
515 }
516
517 void *Lua::GetGlobalPtr(const char *Name)
518 {
519    lua_pushstring(L, Name);
520    lua_rawget(L, LUA_GLOBALSINDEX);
521    void *Ret = NULL;
522    if (lua_isuserdata(L, -1))
523       Ret = lua_touserdata(L, -1);
524    lua_remove(L, -1);
525    return Ret;
526 }
527
528 pkgCache::Package *Lua::GetGlobalPkg(const char *Name)
529 {
530    lua_pushstring(L, Name);
531    lua_rawget(L, LUA_GLOBALSINDEX);
532    pkgCache::Package *Ret;
533    checkudata(pkgCache::Package*, Ret, -1);
534    lua_remove(L, -1);
535    return Ret;
536 }
537
538 vector<pkgCache::Package*> Lua::GetGlobalPkgList(const char *Name)
539 {
540    vector<pkgCache::Package*> Ret;
541    lua_pushstring(L, Name);
542    lua_rawget(L, LUA_GLOBALSINDEX);
543    int t = lua_gettop(L);
544    if (lua_istable(L, t)) {
545       lua_pushnil(L);
546       while (lua_next(L, t) != 0) {
547          pkgCache::Package *Pkg;
548          checkudata(pkgCache::Package*, Pkg, -1);
549          if (Pkg)
550             Ret.push_back(Pkg);
551          lua_pop(L, 1);
552       }
553    }
554    lua_remove(L, -1);
555    return Ret;
556 }
557
558 void Lua::SetDepCache(pkgDepCache *DepCache_)
559 {
560    DepCache = DepCache_;
561    if (DepCache != NULL)
562       Cache = &DepCache->GetCache();
563    else
564       Cache = NULL;
565 }
566
567 void Lua::SetCacheControl(LuaCacheControl *CacheControl_)
568 {
569    CacheControl = CacheControl_;
570 }
571
572 pkgDepCache *Lua::GetDepCache(lua_State *L)
573 {
574    if (DepCache == NULL && CacheControl)
575       SetDepCache(CacheControl->Open());
576    if (DepCache == NULL && L != NULL) {
577       lua_pushstring(L, "no depcache available at that point");
578       lua_error(L);
579    }
580    return DepCache;
581 }
582
583 pkgCache *Lua::GetCache(lua_State *L)
584 {
585    if (Cache == NULL && CacheControl)
586       SetDepCache(CacheControl->Open());
587    if (Cache == NULL && L != NULL) {
588       lua_pushstring(L, "no cache available at that point");
589       lua_error(L);
590    }
591    return Cache;
592 }
593
594 inline pkgCache::Package *AptAux_ToPackage(lua_State *L, int n)
595 {
596    if (lua_isstring(L, n)) {
597       pkgCache *Cache = _lua->GetCache(L);
598       if (Cache == NULL)
599          return NULL;
600       const char *Name = lua_tostring(L, n);
601       return (pkgCache::Package*)Cache->FindPackage(Name);
602    } else {
603       pkgCache::Package *Pkg;
604       checkudata(pkgCache::Package*, Pkg, n);
605       if (Pkg == NULL)
606          luaL_argerror(L, n, "invalid package");
607       return Pkg;
608    }
609 }
610
611 static pkgCache::PkgIterator *AptAux_ToPkgIterator(lua_State *L, int n)
612 {
613    pkgCache::Package *Pkg = AptAux_ToPackage(L, n);
614    if (Pkg == NULL)
615       return NULL;
616    pkgCache *Cache = _lua->GetCache(L);
617    if (Cache == NULL)
618       return NULL;
619    return new pkgCache::PkgIterator(*Cache, Pkg);
620 }
621
622 inline pkgCache::Version *AptAux_ToVersion(lua_State *L, int n)
623 {
624    pkgCache::Version *Ver;
625    checkudata(pkgCache::Version*, Ver, n);
626    if (Ver == NULL)
627       luaL_argerror(L, n, "invalid version");
628    return Ver;
629 }
630
631 static pkgCache::VerIterator *AptAux_ToVerIterator(lua_State *L, int n)
632 {
633    pkgCache::Version *Ver = AptAux_ToVersion(L, n);
634    if (Ver == NULL)
635       return NULL;
636    pkgCache *Cache = _lua->GetCache(L);
637    if (Cache == NULL)
638       return NULL;
639    return new pkgCache::VerIterator(*Cache, Ver);
640 }
641
642 inline int AptAux_PushPackage(lua_State *L, pkgCache::Package *Pkg)
643 {
644    if (Pkg != 0) {
645       pushudata(pkgCache::Package*, Pkg);
646       return 1;
647    }
648    return 0;
649 }
650
651 inline int AptAux_PushVersion(lua_State *L, pkgCache::Version *Ver)
652 {
653    if (Ver != 0) {
654       pushudata(pkgCache::Version*, Ver);
655       return 1;
656    }
657    return 0;
658 }
659
660 static int AptAux_PushVersion(lua_State *L, map_ptrloc Loc)
661 {
662    pkgCache *Cache = _lua->GetCache(L);
663    if (Cache == NULL)
664       return 0;
665    if (Loc != 0) {
666       pkgCache::Version *Ver = Cache->VerP+Loc;
667       if (Ver != 0) {
668          pushudata(pkgCache::Version*, Ver);
669          return 1;
670       }
671    }
672    return 0;
673 }
674
675 static int AptAux_PushCacheString(lua_State *L, map_ptrloc Pos)
676 {
677    if (Pos == 0)
678       return 0;
679    pkgCache *Cache = _lua->GetCache(L);
680    if (Cache == NULL)
681       return 0;
682    const char *Str = Cache->StrP+Pos;
683    lua_pushstring(L, Str);
684    return 1;
685 }
686
687 inline int AptAux_PushBool(lua_State *L, bool Value)
688 {
689    if (Value == true) {
690       lua_pushnumber(L, 1);
691       return 1;
692    }
693    return 0;
694 }
695
696 #define MARK_KEEP      0
697 #define MARK_INSTALL   1
698 #define MARK_REINSTALL 2
699 #define MARK_REMOVE    3
700
701 static int AptAux_mark(lua_State *L, int Kind)
702 {
703    pkgCache::Package *Pkg = AptAux_ToPackage(L, 1);
704    if (Pkg != NULL) {
705       pkgDepCache *DepCache = _lua->GetDepCache(L);
706       if (DepCache == NULL)
707          return 0;
708       pkgProblemResolver *MyFix = NULL;
709       pkgProblemResolver *Fix = _lua->GetProblemResolver();
710       if (Fix == NULL)
711          Fix = MyFix = new pkgProblemResolver(DepCache);
712       pkgCache::PkgIterator PkgI(DepCache->GetCache(), Pkg);
713       Fix->Clear(PkgI);
714       Fix->Protect(PkgI);
715       switch (Kind) {
716          case MARK_KEEP:
717             DepCache->MarkKeep(PkgI);
718             break;
719          case MARK_INSTALL:
720             DepCache->MarkInstall(PkgI);
721             break;
722          case MARK_REINSTALL:
723             DepCache->SetReInstall(PkgI, true);
724             break;
725          case MARK_REMOVE:
726             Fix->Remove(PkgI);
727             DepCache->MarkDelete(PkgI);
728             break;
729       }
730       if (_lua->GetDontFix() == false && DepCache->BrokenCount() > 0) {
731          if (Kind != MARK_KEEP) {
732             Fix->Resolve(false);
733          } else {
734             Fix->InstallProtect();
735             Fix->Resolve(true);
736          }
737       }
738       delete MyFix;
739    }
740    return 0;
741 }
742
743 static int AptAux_marksimple(lua_State *L, int Kind)
744 {
745    pkgCache::Package *Pkg = AptAux_ToPackage(L, 1);
746    if (Pkg != NULL) {
747       pkgDepCache *DepCache = _lua->GetDepCache(L);
748       if (DepCache == NULL)
749          return 0;
750       pkgCache::PkgIterator PkgI(DepCache->GetCache(), Pkg);
751       pkgDepCache::State state(DepCache);
752       switch (Kind) {
753          case MARK_KEEP:
754             DepCache->MarkKeep(PkgI);
755             break;
756          case MARK_INSTALL:
757             DepCache->MarkInstall(PkgI, false);
758             break;
759          case MARK_REMOVE:
760             DepCache->MarkDelete(PkgI);
761             break;
762       }
763       if (DepCache->BrokenCount() > 0)
764          state.Restore();
765    }
766    return 0;
767 }
768
769 static int AptLua_confget(lua_State *L)
770 {
771    const char *key = luaL_checkstring(L, 1);
772    const char *def = luaL_optstring(L, 2, "");
773    string Value;
774    if (key != NULL)
775       Value = _config->FindAny(key, def);
776    lua_pushstring(L, Value.c_str());
777    return 1;
778 }
779
780 static int AptLua_confgetlist(lua_State *L)
781 {
782    const char *key = luaL_checkstring(L, 1);
783    if (key == NULL)
784       return 0;
785    const Configuration::Item *Top = _config->Tree(key);
786    lua_newtable(L);
787    int i = 1;
788    for (Top = (Top == 0?0:Top->Child); Top != 0; Top = Top->Next) {
789        if (Top->Value.empty() == true)
790           continue;
791        lua_pushstring(L, Top->Value.c_str());
792        lua_rawseti(L, -2, i++);
793    }
794    return 1;
795 }
796
797 static int AptLua_confset(lua_State *L)
798 {
799    const char *key = luaL_checkstring(L, 1);
800    const char *val = luaL_checkstring(L, 2);
801    int cnd = 0;
802    if (lua_gettop(L) >= 3 && lua_isboolean(L, 3))
803       cnd = lua_toboolean(L, 3);
804    else
805       cnd = luaL_optint(L, 3, 0);
806    if (key != NULL && val != NULL) {
807       if (cnd != 0)
808          _config->CndSet(key, val);
809       else
810          _config->Set(key, val);
811    }
812    return 0;
813 }
814
815 static int AptLua_confexists(lua_State *L)
816 {
817    const char *key = luaL_checkstring(L, 1);
818    if (key == NULL)
819       return 0;
820    if (_config->Exists(key) == true)
821       lua_pushnumber(L, 1);
822    else
823       lua_pushnil(L);
824    return 1;
825 }
826
827 static int AptLua_confclear(lua_State *L)
828 {
829    const char *key = luaL_checkstring(L, 1);
830    if (key != NULL)
831       _config->Clear(key);
832    return 0;
833 }
834
835
836 static int AptLua_pkgfind(lua_State *L)
837 {
838    const char *name = luaL_checkstring(L, 1);
839    if (name == NULL)
840       return 0;
841    pkgCache *Cache = _lua->GetCache(L);
842    if (Cache == NULL)
843       return 0;
844    return AptAux_PushPackage(L, Cache->FindPackage(name));
845 }
846
847 static int AptLua_pkglist(lua_State *L)
848 {
849    pkgCache *Cache = _lua->GetCache(L);
850    if (Cache == NULL)
851       return 0;
852    lua_newtable(L);
853    int i = 1;
854    for (pkgCache::PkgIterator PkgI = Cache->PkgBegin();
855         PkgI.end() == false; PkgI++) {
856       pushudata(pkgCache::Package*, PkgI);
857       lua_rawseti(L, -2, i++);
858    }
859    return 1;
860 }
861
862 static int AptLua_pkgname(lua_State *L)
863 {
864    pkgCache::Package *Pkg = AptAux_ToPackage(L, 1);
865    if (Pkg == NULL)
866       return 0;
867    return AptAux_PushCacheString(L, Pkg->Name);
868 }
869
870 static int AptLua_pkgid(lua_State *L)
871 {
872    pkgCache::Package *Pkg = AptAux_ToPackage(L, 1);
873    if (Pkg == NULL)
874       return 0;
875    lua_pushnumber(L, Pkg->ID);
876    return 1;
877 }
878
879 static int AptLua_pkgsummary(lua_State *L)
880 {
881    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
882    if (PkgI == NULL)
883       return 0;
884    if ((*PkgI)->VersionList == 0) {
885       lua_pushstring(L, "");
886    } else {
887       pkgCache *Cache = _lua->GetCache(L);
888       if (Cache == NULL)
889          return 0;
890       pkgRecords Recs(*Cache);
891       pkgRecords::Parser &Parse = 
892                               Recs.Lookup(PkgI->VersionList().FileList());
893       lua_pushstring(L, Parse.ShortDesc().c_str());
894    }
895    return 1;
896 }
897
898 static int AptLua_pkgdescr(lua_State *L)
899 {
900    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
901    if (PkgI == NULL)
902       return 0;
903    if ((*PkgI)->VersionList == 0) {
904       lua_pushstring(L, "");
905    } else {
906       pkgCache *Cache = _lua->GetCache(L);
907       if (Cache == NULL)
908          return 0;
909       pkgRecords Recs(*Cache);
910       pkgRecords::Parser &Parse = Recs.Lookup(PkgI->VersionList().FileList());
911       lua_pushstring(L, Parse.LongDesc().c_str());
912    }
913    return 1;
914 }
915
916 static int AptLua_pkgisvirtual(lua_State *L)
917 {
918    pkgCache::Package *Pkg = AptAux_ToPackage(L, 1);
919    if (Pkg == NULL)
920       return 0;
921    if (Pkg->VersionList == 0)
922       lua_pushnumber(L, 1);
923    else
924       lua_pushnil(L);
925    return 1;
926 }
927
928 static int AptLua_pkgvercur(lua_State *L)
929 {
930    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
931    if (PkgI == NULL)
932       return 0;
933    int Ret = AptAux_PushVersion(L, (*PkgI)->CurrentVer);
934    return Ret;
935 }
936
937 static int AptLua_pkgverinst(lua_State *L)
938 {
939    pkgDepCache *DepCache = _lua->GetDepCache(L);
940    if (DepCache == NULL)
941       return 0;
942    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
943    if (PkgI == NULL)
944       return 0;
945    pkgCache::Version *InstVer = (*DepCache)[(*PkgI)].InstallVer;
946    pkgCache::Version *CurVer = (*PkgI).CurrentVer();
947    if (InstVer == CurVer)
948       InstVer = NULL;
949    return AptAux_PushVersion(L, InstVer);
950 }
951
952 static int AptLua_pkgvercand(lua_State *L)
953 {
954    pkgDepCache *DepCache = _lua->GetDepCache(L);
955    if (DepCache == NULL)
956       return 0;
957    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
958    if (PkgI == NULL)
959       return 0;
960    pkgCache::Version *CandVer = (*DepCache)[(*PkgI)].CandidateVer;
961    pkgCache::Version *CurVer = (*PkgI).CurrentVer();
962    if (CandVer == CurVer)
963       CandVer = NULL;
964    return AptAux_PushVersion(L, CandVer);
965 }
966
967 static int AptLua_pkgverlist(lua_State *L)
968 {
969    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
970    if (PkgI == NULL)
971       return 0;
972    lua_newtable(L);
973    int i = 1;
974    for (pkgCache::VerIterator Ver = (*PkgI).VersionList();
975         Ver.end() == false; Ver++) {
976       pushudata(pkgCache::Version*, Ver);
977       lua_rawseti(L, -2, i++);
978    }
979    return 1;
980 }
981
982 static int AptLua_verpkg(lua_State *L)
983 {
984    pkgCache::VerIterator *VerI = AptAux_ToVerIterator(L, 1);
985    if (VerI == NULL)
986       return 0;
987    pushudata(pkgCache::Package*, VerI->ParentPkg());
988    return 1;
989 }
990
991 static int AptLua_verstr(lua_State *L)
992 {
993    pkgCache::Version *Ver = AptAux_ToVersion(L, 1);
994    if (Ver == NULL)
995       return 0;
996    return AptAux_PushCacheString(L, Ver->VerStr);
997 }
998
999 static int AptLua_verarch(lua_State *L)
1000 {
1001    pkgCache::Version *Ver = AptAux_ToVersion(L, 1);
1002    if (Ver == NULL)
1003       return 0;
1004    return AptAux_PushCacheString(L, Ver->Arch);
1005    
1006 }
1007
1008 static int AptLua_verid(lua_State *L)
1009 {
1010    pkgCache::Version *Ver = AptAux_ToVersion(L, 1);
1011    if (Ver == NULL)
1012       return 0;
1013    lua_pushnumber(L, Ver->ID);
1014    return 1;
1015    
1016 }
1017
1018 static int AptLua_verisonline(lua_State *L)
1019 {
1020    pkgCache::VerIterator *VerI = AptAux_ToVerIterator(L, 1);
1021    if (VerI == NULL)
1022       return 0;
1023    return AptAux_PushBool(L, VerI->Downloadable());
1024 }
1025
1026 static int AptLua_verprovlist(lua_State *L)
1027 {
1028    pkgCache::VerIterator *VerI = AptAux_ToVerIterator(L, 1);
1029    if (VerI == NULL)
1030       return 0;
1031    pkgCache::PrvIterator PrvI = VerI->ProvidesList();
1032    lua_newtable(L);
1033    int i = 1;
1034    for (; PrvI.end() == false; PrvI++) {
1035       lua_newtable(L);
1036       lua_pushstring(L, "pkg");
1037       pushudata(pkgCache::Package*, PrvI.ParentPkg());
1038       lua_settable(L, -3);
1039       lua_pushstring(L, "name");
1040       lua_pushstring(L, PrvI.Name());
1041       lua_settable(L, -3);
1042 #ifndef DEAD
1043       lua_pushstring(L, "version");
1044       if (PrvI.ProvideVersion())
1045          lua_pushstring(L, PrvI.ProvideVersion());
1046       else
1047          lua_pushstring(L, "");
1048       lua_settable(L, -3);
1049 #endif
1050       lua_pushstring(L, "verstr");
1051       if (PrvI.ProvideVersion())
1052          lua_pushstring(L, PrvI.ProvideVersion());
1053       else
1054          lua_pushstring(L, "");
1055       lua_settable(L, -3);
1056       lua_rawseti(L, -2, i++);
1057    }
1058    return 1;
1059 }
1060
1061 static int AptLua_verdeplist(lua_State *L)
1062 {
1063    const char *TypeStr[] = {
1064       "", "depends", "predepends", "suggests", "recommends",
1065       "conflicts", "replaces", "obsoletes"
1066    };
1067    pkgCache::VerIterator *VerI = AptAux_ToVerIterator(L, 1);
1068    if (VerI == NULL)
1069       return 0;
1070    pkgCache::DepIterator DepI = VerI->DependsList();
1071    lua_newtable(L);
1072    int i = 1;
1073    for (; DepI.end() == false; DepI++) {
1074       lua_newtable(L);
1075       lua_pushstring(L, "pkg");
1076       pushudata(pkgCache::Package*, DepI.TargetPkg());
1077       lua_settable(L, -3);
1078       lua_pushstring(L, "name");
1079       lua_pushstring(L, DepI.TargetPkg().Name());
1080       lua_settable(L, -3);
1081       lua_pushstring(L, "verstr");
1082       if (DepI.TargetVer())
1083          lua_pushstring(L, DepI.TargetVer());
1084       else
1085          lua_pushstring(L, "");
1086       lua_settable(L, -3);
1087       lua_pushstring(L, "operator");
1088       lua_pushstring(L, DepI.CompType());
1089       lua_settable(L, -3);
1090       lua_pushstring(L, "type");
1091       lua_pushstring(L, TypeStr[DepI->Type]);
1092       lua_settable(L, -3);
1093       lua_pushstring(L, "verlist");
1094       lua_newtable(L);
1095       pkgCache::Version **VerList = DepI.AllTargets();
1096       for (int j = 0; VerList[j]; j++) {
1097          pushudata(pkgCache::Version*, VerList[j]);
1098          lua_rawseti(L, -2, j+1);
1099       }
1100       delete[] VerList;
1101       lua_settable(L, -3);
1102       lua_rawseti(L, -2, i++);
1103    }
1104    return 1;
1105 }
1106
1107 static int AptLua_verfilelist(lua_State *L)
1108 {
1109    pkgCache::VerIterator *VerI = AptAux_ToVerIterator(L, 1);
1110    if (VerI == NULL)
1111       return 0;
1112    pkgCache *Cache = _lua->GetCache(L);
1113    if (Cache == NULL)
1114       return 0;
1115    pkgRecords Recs(*Cache);
1116    pkgRecords::Parser &Parse = Recs.Lookup(VerI->FileList());
1117
1118    vector<string> Files;
1119    if (Parse.FileList(Files) == false)
1120       return 0;
1121
1122    lua_newtable(L);
1123    int i = 1;
1124    vector<string>::iterator FI = Files.begin();
1125    for (; FI != Files.end(); FI++) {
1126       lua_pushstring(L, (*FI).c_str());
1127       lua_rawseti(L, -2, i++);
1128    }
1129    return 1;
1130 }
1131
1132 static int AptLua_verchangeloglist(lua_State *L)
1133 {
1134    pkgCache::VerIterator *VerI = AptAux_ToVerIterator(L, 1);
1135    if (VerI == NULL)
1136       return 0;
1137    pkgCache *Cache = _lua->GetCache(L);
1138    if (Cache == NULL)
1139       return 0;
1140    pkgRecords Recs(*Cache);
1141    pkgRecords::Parser &Parse = Recs.Lookup(VerI->FileList());
1142
1143    vector<ChangeLogEntry *> ChangeLog;
1144    if (Parse.ChangeLog(ChangeLog) == false)
1145       return 0;
1146
1147    lua_newtable(L);
1148    int i = 1;
1149    vector<ChangeLogEntry *>::iterator CI = ChangeLog.begin();
1150    for (; CI != ChangeLog.end(); CI++) {
1151       lua_newtable(L);
1152       lua_pushstring(L, "time");
1153       lua_pushnumber(L, (*CI)->Time);
1154       lua_settable(L, -3);
1155       lua_pushstring(L, "author");
1156       lua_pushstring(L, (*CI)->Author.c_str());
1157       lua_settable(L, -3);
1158       lua_pushstring(L, "text");
1159       lua_pushstring(L, (*CI)->Text.c_str());
1160       lua_settable(L, -3);
1161       lua_rawseti(L, -2, i++);
1162    }
1163    return 1;
1164 }
1165
1166 static int AptLua_verstrcmp(lua_State *L)
1167 {
1168    const char *Ver1, *Ver2;
1169    const char *Arch1, *Arch2;
1170    int Top = lua_gettop(L);
1171    int Ret = -9999;
1172    bool Error = false;
1173    if (Top == 2) {
1174       Ver1 = luaL_checkstring(L, 1);
1175       Ver2 = luaL_checkstring(L, 2);
1176       if (Ver1 == NULL || Ver2 == NULL)
1177          Error = true;
1178       else
1179          Ret = _system->VS->CmpVersion(Ver1, Ver2);
1180    } else if (Top == 4) {
1181       Ver1 = luaL_checkstring(L, 1);
1182       Arch1 = luaL_checkstring(L, 2);
1183       Ver2 = luaL_checkstring(L, 3);
1184       Arch2 = luaL_checkstring(L, 4);
1185       if (Ver1 == NULL || Arch1 == NULL || Ver2 == NULL || Arch2 == NULL)
1186          Error = true;
1187       else
1188          Ret = _system->VS->CmpVersionArch(Ver1, Arch1, Ver2, Arch2);
1189    } else {
1190       Error = true;
1191    }
1192    if (Error == true) {
1193       lua_pushstring(L, "verstrcmp requires 2 or 4 string arguments");
1194       lua_error(L);
1195       return 0;
1196    } else {
1197       lua_pushnumber(L, Ret);
1198       return 1;
1199    }
1200 }
1201
1202 static int AptLua_markkeep(lua_State *L)
1203 {
1204    return AptAux_mark(L, MARK_KEEP);
1205 }
1206
1207 static int AptLua_markinstall(lua_State *L)
1208 {
1209    return AptAux_mark(L, MARK_INSTALL);
1210 }
1211
1212 static int AptLua_markreinstall(lua_State *L)
1213 {
1214    _config->Set("Apt::Get::ReInstall", true);
1215    return AptAux_mark(L, MARK_REINSTALL);
1216 }
1217
1218 static int AptLua_markremove(lua_State *L)
1219 {
1220    return AptAux_mark(L, MARK_REMOVE);
1221 }
1222
1223 static int AptLua_marksimpleinstall(lua_State *L)
1224 {
1225    return AptAux_marksimple(L, MARK_INSTALL);
1226 }
1227
1228 static int AptLua_markdistupgrade(lua_State *L)
1229 {
1230    if (lua_gettop(L) != 0) {
1231       lua_pushstring(L, "markdistupgrade has no arguments");
1232       lua_error(L);
1233       return 0;
1234    }
1235    pkgDepCache *DepCache = _lua->GetDepCache(L);
1236    if (DepCache != NULL)
1237       pkgDistUpgrade(*DepCache);
1238    return 0;
1239 }
1240
1241 static int AptLua_markupgrade(lua_State *L)
1242 {
1243    if (lua_gettop(L) != 0) {
1244       lua_pushstring(L, "markdistupgrade has no arguments");
1245       lua_error(L);
1246       return 0;
1247    }
1248    pkgDepCache *DepCache = _lua->GetDepCache(L);
1249    if (DepCache != NULL)
1250       pkgAllUpgrade(*DepCache);
1251    return 0;
1252 }
1253
1254 static int AptLua_statkeep(lua_State *L)
1255 {
1256    pkgDepCache *DepCache = _lua->GetDepCache(L);
1257    if (DepCache == NULL)
1258       return 0;
1259    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1260    if (PkgI == NULL)
1261       return 0;
1262    return AptAux_PushBool(L,
1263                 (*DepCache)[*PkgI].Keep() &&
1264                 !((*DepCache)[*PkgI].iFlags & pkgDepCache::ReInstall));
1265 }
1266
1267 static int AptLua_statinstall(lua_State *L)
1268 {
1269    pkgDepCache *DepCache = _lua->GetDepCache(L);
1270    if (DepCache == NULL)
1271       return 0;
1272    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1273    if (PkgI == NULL)
1274       return 0;
1275    return AptAux_PushBool(L, (*DepCache)[*PkgI].Install());
1276 }
1277
1278 static int AptLua_statremove(lua_State *L)
1279 {
1280    pkgDepCache *DepCache = _lua->GetDepCache(L);
1281    if (DepCache == NULL)
1282       return 0;
1283    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1284    if (PkgI == NULL)
1285       return 0;
1286    return AptAux_PushBool(L, (*DepCache)[*PkgI].Delete());
1287 }
1288
1289 static int AptLua_statnewinstall(lua_State *L)
1290 {
1291    pkgDepCache *DepCache = _lua->GetDepCache(L);
1292    if (DepCache == NULL)
1293       return 0;
1294    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1295    if (PkgI == NULL)
1296       return 0;
1297    return AptAux_PushBool(L, (*DepCache)[*PkgI].NewInstall());
1298 }
1299
1300 static int AptLua_statreinstall(lua_State *L)
1301 {
1302    pkgDepCache *DepCache = _lua->GetDepCache(L);
1303    if (DepCache == NULL)
1304       return 0;
1305    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1306    if (PkgI == NULL)
1307       return 0;
1308    return AptAux_PushBool(L,
1309                 (*DepCache)[*PkgI].Keep() &&
1310                 ((*DepCache)[*PkgI].iFlags & pkgDepCache::ReInstall));
1311 }
1312
1313 static int AptLua_statupgrade(lua_State *L)
1314 {
1315    pkgDepCache *DepCache = _lua->GetDepCache(L);
1316    if (DepCache == NULL)
1317       return 0;
1318    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1319    if (PkgI == NULL)
1320       return 0;
1321    return AptAux_PushBool(L, (*DepCache)[*PkgI].Upgrade());
1322 }
1323
1324 static int AptLua_statupgradable(lua_State *L)
1325 {
1326    pkgDepCache *DepCache = _lua->GetDepCache(L);
1327    if (DepCache == NULL)
1328       return 0;
1329    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1330    if (PkgI == NULL)
1331       return 0;
1332    return AptAux_PushBool(L, (*DepCache)[*PkgI].Upgradable());
1333 }
1334
1335 static int AptLua_statdowngrade(lua_State *L)
1336 {
1337    pkgDepCache *DepCache = _lua->GetDepCache(L);
1338    if (DepCache == NULL)
1339       return 0;
1340    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1341    if (PkgI == NULL)
1342       return 0;
1343    return AptAux_PushBool(L, (*DepCache)[*PkgI].Downgrade());
1344 }
1345
1346 static int AptLua_statnowbroken(lua_State *L)
1347 {
1348    pkgDepCache *DepCache = _lua->GetDepCache(L);
1349    if (DepCache == NULL)
1350       return 0;
1351    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1352    if (PkgI == NULL)
1353       return 0;
1354    return AptAux_PushBool(L, (*DepCache)[*PkgI].NowBroken());
1355 }
1356
1357 static int AptLua_statinstbroken(lua_State *L)
1358 {
1359    pkgDepCache *DepCache = _lua->GetDepCache(L);
1360    if (DepCache == NULL)
1361       return 0;
1362    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1363    if (PkgI == NULL)
1364       return 0;
1365    return AptAux_PushBool(L, (*DepCache)[*PkgI].InstBroken());
1366 }
1367
1368 static int AptLua_statstr(lua_State *L)
1369 {
1370    pkgDepCache *DepCache = _lua->GetDepCache(L);
1371    if (DepCache == NULL)
1372       return 0;
1373    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1374    if (PkgI == NULL)
1375       return 0;
1376    pkgDepCache::StateCache &S = (*DepCache)[*PkgI];
1377    if (S.NewInstall()) {
1378       if (S.InstBroken()) {
1379          lua_pushstring(L, "newinstall(broken)");
1380       } else {
1381          lua_pushstring(L, "newinstall");
1382       }
1383    } else if (S.Upgrade()) {
1384       if (S.InstBroken()) {
1385          lua_pushstring(L, "upgrade(broken)");
1386       } else {
1387          lua_pushstring(L, "upgrade");
1388       }
1389    } else if (S.Downgrade()) {
1390       if (S.InstBroken()) {
1391          lua_pushstring(L, "downgrade(broken)");
1392       } else {
1393          lua_pushstring(L, "downgrade");
1394       }
1395    } else if (S.Keep() && (S.iFlags & pkgDepCache::ReInstall)) {
1396       if (S.NowBroken()) {
1397          lua_pushstring(L, "reinstall(broken)");
1398       } else {
1399          lua_pushstring(L, "reinstall");
1400       }
1401    } else if (S.Keep()) {
1402       if (S.NowBroken()) {
1403          lua_pushstring(L, "keep(broken)");
1404       } else {
1405          lua_pushstring(L, "keep");
1406       }
1407    } else if (S.Delete()) {
1408       lua_pushstring(L, "remove");
1409    } else {
1410       lua_pushstring(L, "unknown state in statstr(), "
1411                         "report to the maintainer");
1412       lua_error(L);
1413       return 0;
1414    }
1415    return 1;
1416 }
1417
1418 static int AptLua_apterror(lua_State *L)
1419 {
1420    const char *str = luaL_checkstring(L, 1);
1421    if (str != NULL)
1422       _error->Error("%s", str);
1423    return 0;
1424 }
1425
1426 static int AptLua_aptwarning(lua_State *L)
1427 {
1428    const char *str = luaL_checkstring(L, 1);
1429    if (str != NULL)
1430       _error->Warning("%s", str);
1431    return 0;
1432 }
1433
1434 static int AptLua_gettext(lua_State *L)
1435 {
1436    const char *str = luaL_checkstring(L, 1);
1437    if (str != NULL) {
1438       lua_pushliteral(L, "TEXTDOMAIN");
1439       lua_rawget(L, LUA_GLOBALSINDEX);
1440       if (lua_isstring(L, -1))
1441          lua_pushstring(L, dgettext(lua_tostring(L, -1), str));
1442       else
1443          lua_pushstring(L, gettext(str));
1444       lua_remove(L, -2);
1445       return 1;
1446    }
1447    return 0;
1448 }
1449
1450 static const luaL_reg aptlib[] = {
1451    {"confget",          AptLua_confget},
1452    {"confgetlist",      AptLua_confgetlist},
1453    {"confset",          AptLua_confset},
1454    {"confexists",       AptLua_confexists},
1455    {"confclear",        AptLua_confclear},
1456    {"pkgfind",          AptLua_pkgfind},
1457    {"pkglist",          AptLua_pkglist},
1458    {"pkgname",          AptLua_pkgname},
1459    {"pkgid",            AptLua_pkgid},
1460    {"pkgsummary",       AptLua_pkgsummary},
1461    {"pkgdescr",         AptLua_pkgdescr},
1462    {"pkgisvirtual",     AptLua_pkgisvirtual},
1463    {"pkgvercur",        AptLua_pkgvercur},
1464    {"pkgverinst",       AptLua_pkgverinst},
1465    {"pkgvercand",       AptLua_pkgvercand},
1466    {"pkgverlist",       AptLua_pkgverlist},
1467    {"verpkg",           AptLua_verpkg},
1468    {"verstr",           AptLua_verstr},
1469    {"verarch",          AptLua_verarch},
1470    {"verid",            AptLua_verid},
1471    {"verisonline",      AptLua_verisonline},
1472    {"verprovlist",      AptLua_verprovlist},
1473    {"verdeplist",       AptLua_verdeplist},
1474    {"verfilelist",      AptLua_verfilelist},
1475    {"verchangeloglist", AptLua_verchangeloglist},
1476    {"verstrcmp",        AptLua_verstrcmp},
1477    {"markkeep",         AptLua_markkeep},
1478    {"markinstall",      AptLua_markinstall},
1479    {"markreinstall",    AptLua_markreinstall},
1480    {"markremove",       AptLua_markremove},
1481    {"marksimplekeep",   AptLua_marksimpleinstall},
1482    {"marksimpleinstall",AptLua_marksimpleinstall},
1483    {"marksimpleremove", AptLua_marksimpleinstall},
1484    {"markdistupgrade",  AptLua_markdistupgrade},
1485    {"markupgrade",      AptLua_markupgrade},
1486    {"statkeep",         AptLua_statkeep},
1487    {"statinstall",      AptLua_statinstall},
1488    {"statremove",       AptLua_statremove},
1489    {"statnewinstall",   AptLua_statnewinstall},
1490    {"statreinstall",    AptLua_statreinstall},
1491    {"statupgrade",      AptLua_statupgrade},
1492    {"statupgradable",   AptLua_statupgradable},
1493    {"statdowngrade",    AptLua_statdowngrade},
1494    {"statnowbroken",    AptLua_statnowbroken},
1495    {"statinstbroken",   AptLua_statinstbroken},
1496    {"statstr",          AptLua_statstr},
1497    {"apterror",         AptLua_apterror},
1498    {"aptwarning",       AptLua_aptwarning},
1499    {"_",                AptLua_gettext},
1500    {NULL, NULL}
1501 };
1502
1503 static int AptLua_vercomp(lua_State *L)
1504 {
1505    pkgCache::Version *v1, *v2;
1506    checkudata(pkgCache::Version*, v1, 1);
1507    checkudata(pkgCache::Version*, v2, 2);
1508    lua_pushboolean(L, (!v1 || v1 != v2) ? 0 : 1);
1509    return 1;
1510 }
1511
1512 static int AptLua_pkgcomp(lua_State *L)
1513 {
1514    pkgCache::Package *p1, *p2;
1515    checkudata(pkgCache::Package*, p1, 1);
1516    checkudata(pkgCache::Package*, p2, 2);
1517    lua_pushboolean(L, (!p1 || p1 != p2) ? 0 : 1);
1518    return 1;
1519 }
1520
1521
1522 static int luaopen_apt(lua_State *L)
1523 {
1524    lua_pushvalue(L, LUA_GLOBALSINDEX);
1525    luaL_openlib(L, NULL, aptlib, 0);
1526    return 0;
1527 }
1528
1529 pkgDepCache *LuaCacheControl::Open()
1530 {
1531    if (geteuid() == 0)
1532       return Open(true);
1533    else
1534       return Open(false);
1535 }
1536
1537 #endif // APT_WITH_LUA
1538
1539 // vim:sts=3:sw=3