On Sat, May 17, 2008 at 09:34:27AM +0400, Alexey Tourbin wrote: > Теперь остаётся выяснить, сколько это занимает места. > > Обычная генерация сизифа: > > $ cp -prs /ALT/Sisyphus/x86_64 /ALT/Sisyphus/noarch . > $ rm -f x86_64/base/* noarch/base/* > $ PATH=$PWD:$PATH genbasedir --topdir=$PWD x86_64 > $ PATH=$PWD:$PATH genbasedir --topdir=$PWD noarch > $ du -bk x86_64/base/pkglist.classic.bz2 noarch/base/pkglist.classic.bz2 > 2421 x86_64/base/pkglist.classic.bz2 > 1049 noarch/base/pkglist.classic.bz2 > $ > > Генерация с опцией --changelog-since=2007-01-01: > > $ PATH=$PWD:$PATH genbasedir --topdir=$PWD --changelog-since=2007-01-01 x86_64 > $ PATH=$PWD:$PATH genbasedir --topdir=$PWD --changelog-since=2007-01-01 noarch > $ du -bk x86_64/base/pkglist.classic.bz2 noarch/base/pkglist.classic.bz2 > 3536 x86_64/base/pkglist.classic.bz2 > 1302 noarch/base/pkglist.classic.bz2 > $ > > Таким образом, размер скачиваемого при 'apt-get update' заметно > увеличивается (примерно на треть). Я считаю это приемлемой платой > за удовольствие просмотреть changelog пакета ДО скачивания и установки. On Sat, May 17, 2008 at 11:00:34PM +0400, Alexey Tourbin wrote: > Какая плата тебя бы устроила? Думаю что плату можно будет немного > уменьшить, если сначала отсортировать пакеты по %{SOURCERPM}, а уже > потом выгонять хедеры. Тогда bzip2 лучше сожмёт одинаковые changelog'и > подряд идущих подпакетов. Я сделал предварительную реализацию сортировки по %{SOURCERPM}. Результаты теперь такие: $ PATH=$PWD:$PATH genbasedir --topdir=$PWD x86_64 $ PATH=$PWD:$PATH genbasedir --topdir=$PWD noarch $ du -bk x86_64/base/pkglist.classic.bz2 noarch/base/pkglist.classic.bz2 2384 x86_64/base/pkglist.classic.bz2 1048 noarch/base/pkglist.classic.bz2 $ $ PATH=$PWD:$PATH genbasedir --topdir=$PWD --changelog-since=2007-01-01 x86_64 $ PATH=$PWD:$PATH genbasedir --topdir=$PWD --changelog-since=2007-01-01 noarch $ du -bk x86_64/base/pkglist.classic.bz2 noarch/base/pkglist.classic.bz2 3306 x86_64/base/pkglist.classic.bz2 1300 noarch/base/pkglist.classic.bz2 $ Из этого видно следующее: для noarch пакетов переупорядочивание по %{SOURCERPM} почти ничего не дает. Это связано с тем, что noarch пакеты реже распиливают, а при распиливании названия подпакетов реже отличаются по префиксу (то есть глобального переупорядочивания, которое может повысить степень сжатия, как напр. в случае с lib%name и %name, не происходит). Для x86_64 экономия заметна даже без генерации changelog'ов (2421/2384 = 1.6%, за счёт лучшего совпадения других атрибутов подпакетов), а особенно с changelog'ом (3536/3306 = 7%, за счёт лучшего сжатия одинаковых changelog'ов подряд идущих подпакетов). В принципе выгаданные несколько процентов позволяют мне с большей уверенностью говорить о включении changelog'ов в репозитарий, хотя общая картина остаётся скорее прежней: если включить changelog'и по предложенной схеме, то размер скачиваемого при 'apt-get update' увеличивается примерно на треть. Вот патч на genpkglist.cc, я его плохо проверил, но вроде работает. У меня уже патч на патче сидит и я пока не знаю как его лучше приложить к тому что есть. --- apt-0.5.15lorg2/tools/genpkglist.cc- 2008-05-18 00:48:01 +0400 +++ apt-0.5.15lorg2/tools/genpkglist.cc 2008-05-18 05:14:06 +0400 @@ -320,7 +320,7 @@ done: } bool copyFields(Header h, Header newHeader, - FILE *idxfile, const char *directory, char *filename, + FILE *idxfile, const char *directory, const char *filename, unsigned filesize, map &updateInfo, bool fullFileList) { @@ -460,99 +460,34 @@ void usage() cerr << " one preceding entry (if available)" <d_name, - (*(struct dirent **) b)->d_name); + if (cur > 1) + printf("\b\b\b\b\b\b\b\b\b\b"); + printf(" %04i/%04i", cur, total); + fflush(stdout); } -int scandir(const char * dir, struct dirent *** namelist, - int (* select)(struct dirent *), - int (* cmp)(const void *, const void *)) +struct rpmfile { + const char *basename; + const char *sourcerpm; +}; +static +int rpmfilecmp(const void *a, const void *b) { - DIR *dp = opendir (dir); - struct dirent **v = NULL; - size_t vsize = 0, i; - struct dirent *d; - int save; - - if (dp == NULL) - return -1; - - save = errno; - errno = 0; - - i = 0; - while ((d = readdir (dp)) != NULL) - { - if (select == NULL || (*select) (d)) - { - if (i == vsize) - { - struct dirent **newv; - if (vsize == 0) - vsize = 10; - else - vsize *= 2; - newv = (struct dirent **) realloc (v, vsize * sizeof (*v)); - if (newv == NULL) - { - lose: - errno = ENOMEM; - break; - } - v = newv; - } - - v[i] = (struct dirent *) malloc (d->d_reclen); - if (v[i] == NULL) - goto lose; - - // *v[i++] = *d; - memcpy(v[i], d, d->d_reclen); - i++; - } - } - - v[i] = NULL; - - if (errno != 0) - { - save = errno; - (void) closedir (dp); - while (i > 0) - free (v[--i]); - free (v); - errno = save; - return -1; - } - - (void) closedir (dp); - errno = save; - - /* Sort the list if we have a comparison function to sort with. */ - if (cmp != NULL) - qsort (v, i, sizeof (struct dirent *), cmp); - - *namelist = v; - return i; + const struct rpmfile *A = (struct rpmfile *)a; + const struct rpmfile *B = (struct rpmfile *)b; + int cmp = strcmp(A->sourcerpm, B->sourcerpm); + if (cmp) + return cmp; + return strcmp(A->basename, B->basename); } -// end of new stuff from glibc -#endif /* !HAVE_SCANDIR */ - int main(int argc, char ** argv) { string rpmsdir; string pkglist_path; - FD_t outfd, fd; - struct dirent **dirEntries; - int entry_no, entry_cur; map updateInfo; CachedMD5 *md5cache; char *op_dir; @@ -561,13 +496,13 @@ int main(int argc, char ** argv) char *op_update = NULL; long /* time_t */ changelog_since = 0; FILE *idxfile; - int i; bool fullFileList = false; bool progressBar = false; const char *pkgListSuffix = NULL; bool pkgListAppend = false; setlocale(LC_ALL, "C"); + int i; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--index") == 0) { i++; @@ -674,14 +609,16 @@ int main(int argc, char ** argv) string dirtag = "RPMS." + string(op_suf); - entry_no = scandir(rpmsdir.c_str(), &dirEntries, selectDirent, alphasort); - if (entry_no < 0) { - cerr << "genpkglist: error opening directory " << rpmsdir << ":" - << strerror(errno); - return 1; + if (chdir(rpmsdir.c_str())) { + perror(rpmsdir.c_str()); + exit(1); + } + + glob_t gl; + if (glob("*.rpm", 0, NULL, &gl)) { + cerr << rpmsdir << "/" << "*.rpm: glob failed" <d_name, O_RDONLY, 0666); - if (!fd) - continue; int rc; Header h; #if RPM_VERSION >= 0x040100 rc = rpmReadPackageFile(ts, fd, dirEntries[entry_cur]->d_name, &h); - if (rc == RPMRC_OK || rc == RPMRC_NOTTRUSTED || rc == RPMRC_NOKEY) { + if (rc == RPMRC_OK || rc == RPMRC_NOTTRUSTED || rc == RPMRC_NOKEY) #else rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL); - if (rc == 0) { + if (rc == 0) #endif + { + ; // good + } + else { + cerr << "Warning: " << basename << ": cannot read package header" <d_name, &sb) < 0) { - cerr << "\nWarning: " << strerror(errno) << ": " << - dirEntries[entry_cur]->d_name << endl; - continue; + const char *basename = rpms[ix].basename; + + if (stat(basename, &sb) < 0) { + cerr << "Fatal: " << basename << ": " << strerror(errno) <d_name, O_RDONLY, 0666); + FD_t fd = Fopen(basename, "r"); if (!fd) { - cerr << "\nWarning: " << strerror(errno) << ": " << - dirEntries[entry_cur]->d_name << endl; - continue; + cerr << "Fatal: " << basename << ": " << strerror(errno) <= 0x040100 @@ -822,14 +782,13 @@ int main(int argc, char ** argv) newHeader = headerNew(); copyFields(h, newHeader, idxfile, dirtag.c_str(), - dirEntries[entry_cur]->d_name, + basename, sb.st_size, updateInfo, fullFileList); if (changelog_since > 0) copyChangelog(changelog_since, h, newHeader); - md5cache->MD5ForFile(string(dirEntries[entry_cur]->d_name), - sb.st_mtime, md5); + md5cache->MD5ForFile(string(basename), sb.st_mtime, md5); headerAddEntry(newHeader, CRPMTAG_MD5, RPM_STRING_TYPE, md5, 1); headerWrite(outfd, newHeader, HEADER_MAGIC_YES); @@ -837,8 +796,8 @@ int main(int argc, char ** argv) headerFree(newHeader); headerFree(h); } else { - cerr << "\nWarning: Skipping malformed RPM: " << - dirEntries[entry_cur]->d_name << endl; + cerr << "Fatal: " << basename << ": cannot read package header" <