5 kx
5 kx /**********************************************************************
5 kx
5 kx Copyright 2019 Andrey V.Kosteltsev
5 kx
9 kx Licensed under the Radix cross Linux License, Version 1.0 .
5 kx you may not use this file except in compliance with the License.
5 kx You may obtain a copy of the License at
5 kx
9 kx https://radix-linux.su/licenses/LICENSE-1.0-en_US.txt
5 kx
5 kx Unless required by applicable law or agreed to in writing, software
5 kx distributed under the License is distributed on an "AS IS" BASIS,
5 kx WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
5 kx implied.
5 kx
5 kx **********************************************************************/
5 kx
5 kx #include <config.h>
5 kx
5 kx #include <stdlib.h>
5 kx #include <stdio.h>
5 kx #include <string.h>
5 kx #include <linux/limits.h>
5 kx #include <libgen.h> /* basename(3) */
5 kx #include <unistd.h>
5 kx #include <time.h>
5 kx #include <math.h>
5 kx
5 kx #include <msglog.h>
5 kx #include <wrapper.h>
5 kx
5 kx #include <make-pkglist.h>
5 kx
5 kx #include <cmpvers.h>
5 kx #include <dlist.h>
5 kx #include <btree.h>
5 kx #include <jsmin.h>
5 kx #include <pkglist.h>
5 kx
5 kx
5 kx char *htmlroot = NULL;
5 kx char *hardware = NULL;
5 kx int minimize = 0;
5 kx
5 kx struct dlist *srcpkgs = NULL;
5 kx
5 kx struct dlist *packages = NULL;
5 kx struct dlist *tarballs = NULL;
5 kx
5 kx struct dlist *provides = NULL;
5 kx struct dlist *extern_requires = NULL;
5 kx
5 kx static struct dlist *tree = NULL;
5 kx
5 kx static char *pkgs_fname = NULL,
5 kx *tree_fname = NULL,
5 kx *html_fname = NULL;
5 kx
5 kx static char *pkgs_min_fname = NULL,
5 kx *tree_min_fname = NULL;
5 kx
5 kx static const char *tarball_suffix = "txz";
5 kx
5 kx /***************************************************************
5 kx tarballs List functions:
5 kx =======================
5 kx
5 kx NOTE:
5 kx ----
5 kx TARBALLS is an optional list created in case when we have
5 kx a set of PACKAGES as input of make-pkglist utility. When we
5 kx are working with a set of input PKGLOGs the TARBALLS list
5 kx is not chreated and pointer to the tarballs == NULL.
5 kx */
5 kx void add_tarball( char *tarball )
5 kx {
5 kx tarballs = dlist_append( tarballs, (void *)xstrdup( (const char *)tarball ) );
5 kx }
5 kx
5 kx static void __free_tarball( void *data, void *user_data )
5 kx {
5 kx if( data ) { free( data ); }
5 kx }
5 kx
5 kx void free_tarballs( void )
5 kx {
5 kx if( tarballs ) { dlist_free( tarballs, __free_tarball ); tarballs = NULL; }
5 kx }
5 kx
5 kx static int __compare_tarballs( const void *a, const void *b )
5 kx {
5 kx return strncmp( (const char *)a, (const char *)b, (size_t)strlen((const char *)b) );
5 kx }
5 kx
5 kx const char *find_tarball( const char *name )
5 kx {
5 kx struct dlist *node = NULL;
5 kx
5 kx if( !tarballs || !name ) return NULL;
5 kx
5 kx node = dlist_find_data( tarballs, __compare_tarballs, (const void *)name );
5 kx if( node )
5 kx {
5 kx return (const char *)node->data;
5 kx }
5 kx
5 kx return NULL;
5 kx }
5 kx
5 kx /*********************
5 kx Just for debugging:
5 kx */
5 kx static void __print_tarball( void *data, void *user_data )
5 kx {
5 kx int *counter = (int *)user_data;
5 kx
5 kx if( counter ) { fprintf( stdout, "tarball[%.5d]: %s\n", *counter, (char *)data ); ++(*counter); }
5 kx else { fprintf( stdout, "tarball: %s\n", (char *)data ); }
5 kx }
5 kx
5 kx void print_tarballs( void )
5 kx {
5 kx int cnt = 0;
5 kx if( tarballs ) { dlist_foreach( tarballs, __print_tarball, (void *)&cnt ); }
5 kx }
5 kx /*
5 kx End of tarballs List functions.
5 kx ***************************************************************/
5 kx
5 kx
5 kx
5 kx char *strprio( enum _priority priority, int short_name )
5 kx {
5 kx char *p = NULL;
5 kx
5 kx switch( priority )
5 kx {
5 kx case REQUIRED:
5 kx p = ( short_name ) ? "REQ" : "REQUIRED";
5 kx break;
5 kx case RECOMMENDED:
5 kx p = ( short_name ) ? "REC" : "RECOMMENDED";
5 kx break;
5 kx case OPTIONAL:
5 kx p = ( short_name ) ? "OPT" : "OPTIONAL";
5 kx break;
5 kx case SKIP:
5 kx p = ( short_name ) ? "SKP" : "SKIP";
5 kx break;
5 kx }
5 kx return p;
5 kx }
5 kx
5 kx char *strproc( enum _procedure procedure )
5 kx {
5 kx char *p = NULL;
5 kx
5 kx switch( procedure )
5 kx {
5 kx case INSTALL:
5 kx p = "install";
5 kx break;
5 kx case UPDATE:
5 kx p = "update";
5 kx break;
5 kx }
5 kx return p;
5 kx }
5 kx
5 kx
5 kx /***************************************************************
5 kx PACKAGE functions:
5 kx */
5 kx
5 kx struct pkg *pkg_alloc( void )
5 kx {
5 kx struct pkg *pkg = NULL;
5 kx
5 kx pkg = (struct pkg *)malloc( sizeof( struct pkg ) );
5 kx if( !pkg ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)pkg, sizeof( struct pkg ) );
5 kx
5 kx return pkg;
5 kx }
5 kx
5 kx void pkg_free( struct pkg *pkg )
5 kx {
5 kx if( pkg )
5 kx {
5 kx if( pkg->group ) { free( pkg->group ); pkg->group = NULL; }
5 kx if( pkg->name ) { free( pkg->name ); pkg->name = NULL; }
5 kx if( pkg->version ) { free( pkg->version ); pkg->version = NULL; }
5 kx
5 kx free( pkg );
5 kx }
5 kx }
5 kx
5 kx static void __pkg_free_func( void *data, void *user_data )
5 kx {
5 kx struct pkg *pkg = (struct pkg *)data;
5 kx if( pkg ) { pkg_free( pkg ); }
5 kx }
5 kx
5 kx void free_srcpkgs( void )
5 kx {
5 kx if( srcpkgs ) { dlist_free( srcpkgs, __pkg_free_func ); srcpkgs = NULL; }
5 kx }
5 kx
5 kx void add_srcpkg( struct pkg *pkg )
5 kx {
5 kx srcpkgs = dlist_append( srcpkgs, (void *)pkg );
5 kx }
5 kx
5 kx
5 kx static struct pkginfo *__pkginfo_alloc( void )
5 kx {
5 kx struct pkginfo *pkginfo = NULL;
5 kx
5 kx pkginfo = (struct pkginfo *)malloc( sizeof( struct pkginfo ) );
5 kx if( !pkginfo ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)pkginfo, sizeof( struct pkginfo ) );
5 kx
5 kx return pkginfo;
5 kx }
5 kx
5 kx static void __pkginfo_free( struct pkginfo *pkginfo )
5 kx {
5 kx if( pkginfo )
5 kx {
5 kx if( pkginfo->name ) { free( pkginfo->name ); pkginfo->name = NULL; }
5 kx if( pkginfo->version ) { free( pkginfo->version ); pkginfo->version = NULL; }
5 kx if( pkginfo->arch ) { free( pkginfo->arch ); pkginfo->arch = NULL; }
5 kx if( pkginfo->distro_name ) { free( pkginfo->distro_name ); pkginfo->distro_name = NULL; }
5 kx if( pkginfo->distro_version ) { free( pkginfo->distro_version ); pkginfo->distro_version = NULL; }
5 kx if( pkginfo->group ) { free( pkginfo->group ); pkginfo->group = NULL; }
5 kx if( pkginfo->short_description ) { free( pkginfo->short_description ); pkginfo->short_description = NULL; }
5 kx if( pkginfo->url ) { free( pkginfo->url ); pkginfo->url = NULL; }
5 kx if( pkginfo->license ) { free( pkginfo->license ); pkginfo->license = NULL; }
5 kx
5 kx free( pkginfo );
5 kx }
5 kx }
5 kx
5 kx
5 kx static struct references *__references_alloc( void )
5 kx {
5 kx struct references *references = NULL;
5 kx
5 kx references = (struct references *)malloc( sizeof( struct references ) );
5 kx if( !references ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)references, sizeof( struct references ) );
5 kx
5 kx return references;
5 kx }
5 kx
5 kx static void __references_free( struct references *references )
5 kx {
5 kx if( references )
5 kx {
5 kx if( references->list ) { dlist_free( references->list, __pkg_free_func ); references->list = NULL; }
5 kx free( references );
5 kx }
5 kx }
5 kx
5 kx
5 kx static struct requires *__requires_alloc( void )
5 kx {
5 kx struct requires *requires = NULL;
5 kx
5 kx requires = (struct requires *)malloc( sizeof( struct requires ) );
5 kx if( !requires ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)requires, sizeof( struct requires ) );
5 kx
5 kx return requires;
5 kx }
5 kx
5 kx static void __requires_free( struct requires *requires )
5 kx {
5 kx if( requires )
5 kx {
5 kx if( requires->list ) { dlist_free( requires->list, __pkg_free_func ); requires->list = NULL; }
5 kx free( requires );
5 kx }
5 kx }
5 kx
5 kx
5 kx static struct files *__files_alloc( void )
5 kx {
5 kx struct files *files = NULL;
5 kx
5 kx files = (struct files *)malloc( sizeof( struct files ) );
5 kx if( !files ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)files, sizeof( struct files ) );
5 kx
5 kx return files;
5 kx }
5 kx
5 kx static void __files_free_func( void *data, void *user_data )
5 kx {
5 kx if( data ) { free( data ); }
5 kx }
5 kx
5 kx static void __files_free( struct files *files )
5 kx {
5 kx if( files )
5 kx {
5 kx if( files->list ) { dlist_free( files->list, __files_free_func ); files->list = NULL; }
5 kx free( files );
5 kx }
5 kx }
5 kx
5 kx
5 kx struct package *package_alloc( void )
5 kx {
5 kx struct package *package = NULL;
5 kx struct pkginfo *pkginfo = __pkginfo_alloc();
5 kx struct references *references = __references_alloc();
5 kx struct requires *requires = __requires_alloc();
5 kx struct files *files = __files_alloc();
5 kx
5 kx package = (struct package *)malloc( sizeof( struct package ) );
5 kx if( !package ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)package, sizeof( struct package ) );
5 kx
5 kx package->pkginfo = pkginfo;
5 kx package->references = references;
5 kx package->requires = requires;
5 kx package->files = files;
5 kx
5 kx return package;
5 kx }
5 kx
5 kx void package_free( struct package *package )
5 kx {
5 kx if( package )
5 kx {
5 kx if( package->pkginfo ) { __pkginfo_free( package->pkginfo ); package->pkginfo = NULL; }
5 kx if( package->references ) { __references_free( package->references ); package->references = NULL; }
5 kx if( package->requires ) { __requires_free( package->requires ); package->requires = NULL; }
5 kx if( package->files ) { __files_free( package->files ); package->files = NULL; }
5 kx
5 kx if( package->description ) { free( package->description ); package->description = NULL; }
5 kx if( package->restore_links ) { free( package->restore_links ); package->restore_links = NULL; }
5 kx if( package->install_script ) { free( package->install_script ); package->install_script = NULL; }
5 kx if( package->hardware ) { free( package->hardware ); package->hardware = NULL; }
5 kx if( package->tarball ) { free( package->tarball ); package->tarball = NULL; }
5 kx
5 kx free( package );
5 kx }
5 kx }
5 kx
5 kx static void __package_free_func( void *data, void *user_data )
5 kx {
5 kx struct package *package = (struct package *)data;
5 kx if( package ) { package_free( package ); }
5 kx }
5 kx
5 kx void free_packages( void )
5 kx {
5 kx if( packages ) { dlist_free( packages, __package_free_func ); packages = NULL; }
5 kx }
5 kx
5 kx
5 kx static int __compare_packages( const void *a, const void *b )
5 kx {
5 kx int ret = -1;
5 kx
5 kx struct package *pkg1 = (struct package *)a;
5 kx struct package *pkg2 = (struct package *)b;
5 kx
5 kx if( pkg1->pkginfo->group && pkg2->pkginfo->group )
5 kx {
5 kx ret = strcmp( pkg1->pkginfo->group, pkg2->pkginfo->group );
5 kx }
5 kx else if( !pkg1->pkginfo->group && !pkg2->pkginfo->group )
5 kx {
5 kx ret = 0;
5 kx }
5 kx else if( pkg1->pkginfo->group )
5 kx {
5 kx ret = 1;
5 kx }
5 kx
5 kx if( ! ret )
5 kx {
5 kx return strcmp( pkg1->pkginfo->name, pkg2->pkginfo->name );
5 kx }
5 kx return ret;
5 kx }
5 kx
5 kx static int __compare_packages_with_version( const void *a, const void *b )
5 kx {
5 kx int ret = -1;
5 kx
5 kx struct package *pkg1 = (struct package *)a;
5 kx struct package *pkg2 = (struct package *)b;
5 kx
5 kx if( pkg1->pkginfo->group && pkg2->pkginfo->group )
5 kx {
5 kx ret = strcmp( pkg1->pkginfo->group, pkg2->pkginfo->group );
5 kx }
5 kx else if( !pkg1->pkginfo->group && !pkg2->pkginfo->group )
5 kx {
5 kx ret = 0;
5 kx }
5 kx else if( pkg1->pkginfo->group )
5 kx {
5 kx ret = 1;
5 kx }
5 kx
5 kx if( ! ret )
5 kx {
5 kx ret = strcmp( pkg1->pkginfo->name, pkg2->pkginfo->name );
5 kx if( ! ret )
5 kx {
5 kx return cmp_version( (const char *)pkg1->pkginfo->version, (const char *)pkg2->pkginfo->version );
5 kx }
5 kx }
5 kx return ret;
5 kx }
5 kx
5 kx
5 kx void add_package( struct package *package )
5 kx {
5 kx packages = dlist_append( packages, (void *)package );
5 kx }
5 kx
5 kx void add_reference( struct package *package, struct pkg *pkg )
5 kx {
5 kx if( package && package->references && pkg )
5 kx {
5 kx package->references->list = dlist_append( package->references->list, (void *)pkg );
5 kx package->references->size = dlist_length( package->references->list );
5 kx }
5 kx }
5 kx
5 kx void add_required( struct package *package, struct pkg *pkg )
5 kx {
5 kx if( package && package->requires && pkg )
5 kx {
5 kx package->requires->list = dlist_append( package->requires->list, (void *)pkg );
5 kx package->requires->size = dlist_length( package->requires->list );
5 kx }
5 kx }
5 kx
5 kx void add_file( struct package *package, const char *fname )
5 kx {
5 kx if( package && package->files && fname )
5 kx {
5 kx package->files->list = dlist_append( package->files->list, (void *)xstrdup( (const char *)fname ) );
5 kx package->files->size = dlist_length( package->files->list );
5 kx }
5 kx }
5 kx
5 kx /*********************
5 kx Just for debugging:
5 kx */
5 kx static void __print_reference( void *data, void *user_data )
5 kx {
5 kx struct pkg *pkg = (struct pkg *)data;
5 kx
5 kx if( pkg )
5 kx {
5 kx if( pkg->group ) { fprintf( stdout, "reference: %s/%s=%s\n", pkg->group, pkg->name, pkg->version ); }
5 kx else { fprintf( stdout, "reference: %s=%s\n", pkg->name, pkg->version ); }
5 kx }
5 kx }
5 kx
5 kx void package_print_references( struct package *package )
5 kx {
5 kx if( !package ) return;
5 kx
5 kx if( package->references->list )
5 kx {
5 kx dlist_foreach( package->references->list, __print_reference, NULL );
5 kx }
5 kx }
5 kx
5 kx static void __print_required( void *data, void *user_data )
5 kx {
5 kx struct pkg *pkg = (struct pkg *)data;
5 kx
5 kx if( pkg )
5 kx {
5 kx if( pkg->group ) { fprintf( stdout, "required: %s/%s=%s\n", pkg->group, pkg->name, pkg->version ); }
5 kx else { fprintf( stdout, "required: %s=%s\n", pkg->name, pkg->version ); }
5 kx }
5 kx }
5 kx
5 kx void package_print_requires( struct package *package )
5 kx {
5 kx if( !package ) return;
5 kx
5 kx if( package->requires->list )
5 kx {
5 kx dlist_foreach( package->requires->list, __print_required, NULL );
5 kx }
5 kx }
5 kx
5 kx static void __print_file( void *data, void *user_data )
5 kx {
5 kx int *counter = (int *)user_data;
5 kx
5 kx if( counter ) { fprintf( stdout, "file[%.5d]: %s\n", *counter, (char *)data ); ++(*counter); }
5 kx else { fprintf( stdout, "file: %s\n", (char *)data ); }
5 kx }
5 kx
5 kx void package_print_files( struct package *package )
5 kx {
5 kx int cnt = 0;
5 kx
5 kx if( !package ) return;
5 kx
5 kx if( package->files->list )
5 kx {
5 kx dlist_foreach( package->files->list, __print_file, (void *)&cnt );
5 kx }
5 kx }
5 kx
5 kx /*
5 kx End of PACKAGES functions.
5 kx ***************************************************************/
5 kx
5 kx /***************************************************************
5 kx Extern REQUIRES list functions:
5 kx */
5 kx
5 kx static int __compare_required( const void *a, const void *b )
5 kx {
5 kx int ret = -1;
5 kx
5 kx struct pkg *pkg1 = (struct pkg *)a;
5 kx struct pkg *pkg2 = (struct pkg *)b;
5 kx
5 kx if( pkg1->group && pkg2->group )
5 kx {
5 kx ret = strcmp( pkg1->group, pkg2->group );
5 kx }
5 kx else if( !pkg1->group && !pkg2->group )
5 kx {
5 kx ret = 0;
5 kx }
5 kx else if( pkg1->group )
5 kx {
5 kx ret = 1;
5 kx }
5 kx
5 kx if( ! ret )
5 kx {
5 kx return strcmp( pkg1->name, pkg2->name );
5 kx }
5 kx return ret;
5 kx }
5 kx
5 kx static int __compare_required_with_version( const void *a, const void *b )
5 kx {
5 kx int ret = -1;
5 kx
5 kx struct pkg *pkg1 = (struct pkg *)a;
5 kx struct pkg *pkg2 = (struct pkg *)b;
5 kx
5 kx if( pkg1->group && pkg2->group )
5 kx {
5 kx ret = strcmp( pkg1->group, pkg2->group );
5 kx }
5 kx else if( !pkg1->group && !pkg2->group )
5 kx {
5 kx ret = 0;
5 kx }
5 kx else if( pkg1->group )
5 kx {
5 kx ret = 1;
5 kx }
5 kx
5 kx if( ! ret )
5 kx {
5 kx ret = strcmp( pkg1->name, pkg2->name );
5 kx if( ! ret )
5 kx {
5 kx return cmp_version( (const char *)pkg1->version, (const char *)pkg2->version );
5 kx }
5 kx }
5 kx return ret;
5 kx }
5 kx
5 kx static void __add_unique_required( void *data, void *user_data )
5 kx {
5 kx struct pkg *pkg = (struct pkg *)data;
5 kx
5 kx if( pkg )
5 kx {
5 kx struct dlist *found = dlist_find_data( extern_requires, __compare_required, (const void *)data );
5 kx
5 kx if( found )
5 kx {
5 kx if( cmp_version( (const char *)((struct pkg *)found->data)->version, (const char *)pkg->version ) )
5 kx {
5 kx char *s = ((struct pkg *)found->data)->version;
5 kx ((struct pkg *)found->data)->version =
5 kx xstrdup( (const char *)max_version( (const char *)((struct pkg *)found->data)->version,
5 kx (const char *)pkg->version ) );
5 kx free( s );
5 kx }
5 kx }
5 kx else
5 kx {
5 kx struct pkg *req = pkg_alloc();
5 kx if( req )
5 kx {
5 kx if( pkg->group )
5 kx {
5 kx req->group = xstrdup( (const char *)pkg->group );
5 kx }
5 kx req->name = xstrdup( (const char *)pkg->name );
5 kx req->version = xstrdup( (const char *)pkg->version );
5 kx
5 kx extern_requires = dlist_append( extern_requires, (void *)req );
5 kx }
5 kx }
5 kx }
5 kx }
5 kx
5 kx static void __fill_extern_requires( void *data, void *user_data )
5 kx {
5 kx struct package *package = (struct package *)data;
5 kx
5 kx if( package )
5 kx {
5 kx struct pkg *provide = pkg_alloc();
5 kx
5 kx if( provide )
5 kx {
5 kx if( package->pkginfo->group )
5 kx {
5 kx provide->group = xstrdup( (const char *)package->pkginfo->group );
5 kx }
5 kx provide->name = xstrdup( (const char *)package->pkginfo->name );
5 kx provide->version = xstrdup( (const char *)package->pkginfo->version );
5 kx
5 kx provides = dlist_append( provides, (void *)provide );
5 kx }
5 kx
5 kx if( package->requires->list )
5 kx {
5 kx dlist_foreach( package->requires->list, __add_unique_required, NULL );
5 kx }
5 kx }
5 kx }
5 kx
5 kx static void __clean_extern_requires( void *data, void *user_data )
5 kx {
5 kx if( data )
5 kx {
5 kx extern_requires = dlist_remove_data( extern_requires, __compare_required_with_version, __pkg_free_func, (const void *)data );
5 kx }
5 kx }
5 kx
5 kx static int __compare_provided_old_package( const void *a, const void *b )
5 kx {
5 kx int ret = -1;
5 kx
5 kx struct package *pkg1 = (struct package *)a;
5 kx struct pkg *pkg2 = (struct pkg *)b;
5 kx
5 kx if( pkg1->pkginfo->group && pkg2->group )
5 kx {
5 kx ret = strcmp( pkg1->pkginfo->group, pkg2->group );
5 kx }
5 kx else if( !pkg1->pkginfo->group && !pkg2->group )
5 kx {
5 kx ret = 0;
5 kx }
5 kx else if( pkg1->pkginfo->group )
5 kx {
5 kx ret = 1;
5 kx }
5 kx
5 kx if( ! ret )
5 kx {
5 kx ret = strcmp( pkg1->pkginfo->name, pkg2->name );
5 kx if( ! ret )
5 kx {
5 kx pkg2->procedure = UPDATE; /* mark as too old */
5 kx return ret;
5 kx }
5 kx }
5 kx return ret;
5 kx }
5 kx
5 kx static void __remove_old_package( void *data, void *user_data )
5 kx {
5 kx packages = dlist_remove_data( packages, __compare_provided_old_package, __package_free_func, (const void *)data );
5 kx }
5 kx
5 kx static void remove_old_packages( void )
5 kx {
5 kx dlist_foreach( extern_requires, __remove_old_package, NULL );
5 kx }
5 kx /*
5 kx End of Extern REQUIRES list functions.
5 kx ***************************************************************/
5 kx
5 kx
5 kx /***************************************************************
5 kx Check REQUIRES functions:
5 kx */
5 kx static int __compare_provided( const void *a, const void *b )
5 kx {
5 kx int ret = -1;
5 kx
5 kx struct package *pkg1 = (struct package *)a;
5 kx struct pkg *pkg2 = (struct pkg *)b;
5 kx
5 kx if( pkg1->pkginfo->group && pkg2->group )
5 kx {
5 kx ret = strcmp( pkg1->pkginfo->group, pkg2->group );
5 kx }
5 kx else if( !pkg1->pkginfo->group && !pkg2->group )
5 kx {
5 kx ret = 0;
5 kx }
5 kx else if( pkg1->pkginfo->group )
5 kx {
5 kx ret = 1;
5 kx }
5 kx
5 kx if( ! ret )
5 kx {
5 kx return strcmp( pkg1->pkginfo->name, pkg2->name );
5 kx }
5 kx return ret;
5 kx }
5 kx
5 kx static int __compare_packages_by_name( const void *a, const void *b )
5 kx {
5 kx int ret = -1;
5 kx
5 kx struct package *pkg1 = (struct package *)a;
5 kx struct package *pkg2 = (struct package *)b;
5 kx
5 kx if( !strcmp( pkg1->pkginfo->name, pkg2->pkginfo->name ) )
5 kx {
5 kx if( pkg1->pkginfo->group && pkg2->pkginfo->group )
5 kx {
5 kx ret = strcmp( pkg1->pkginfo->group, pkg2->pkginfo->group );
5 kx }
5 kx else if( !pkg1->pkginfo->group && !pkg2->pkginfo->group )
5 kx {
5 kx ret = 0;
5 kx }
5 kx else if( pkg1->pkginfo->group )
5 kx {
5 kx ret = 1;
5 kx }
5 kx
5 kx /* returns equal only if groups are not equal */
5 kx if( ret ) return 0;
5 kx }
5 kx
5 kx return ret;
5 kx }
5 kx
5 kx static int check_dependencies( struct package *package )
5 kx {
5 kx struct dlist *list = NULL, *next = NULL, *update = NULL;
5 kx int depended = -1;
5 kx
5 kx if( !package ) return depended;
5 kx depended = 0;
5 kx
5 kx if( !(list = package->requires->list) ) return depended;
5 kx
5 kx while( list )
5 kx {
5 kx next = dlist_next( list );
5 kx {
5 kx int has_extern_dependencies = 0, already_provided = 0;
5 kx
5 kx struct pkg *pkg = (struct pkg *)list->data;
5 kx struct dlist *found = dlist_find_data( extern_requires, __compare_required, (const void *)pkg );
5 kx
5 kx if( found )
5 kx {
5 kx if( cmp_version( (const char *)((struct pkg *)found->data)->version, (const char *)pkg->version ) >= 0 )
5 kx {
5 kx /* required package is found in the extern_requires list */
5 kx has_extern_dependencies += 1;
5 kx }
5 kx }
5 kx
5 kx found = dlist_find_data( provides, __compare_provided, (const void *)pkg );
5 kx if( found )
5 kx {
5 kx if( cmp_version( (const char *)((struct package *)found->data)->pkginfo->version, (const char *)pkg->version ) >= 0 )
5 kx {
5 kx /* required package is found in the extern_requires list */
5 kx already_provided += 1;
5 kx }
5 kx }
5 kx
5 kx if( !already_provided && !has_extern_dependencies ) depended += 1;
5 kx }
5 kx list = next;
5 kx }
5 kx
5 kx /* Check if the package with the same name already exists in the provides list */
5 kx update = dlist_find_data( provides, __compare_packages_by_name, (const void *)package );
5 kx if( update )
5 kx {
5 kx /* Set install procedure to UPDATE: */
5 kx package->procedure = UPDATE;
5 kx }
5 kx
5 kx return depended;
5 kx }
5 kx /*
5 kx End of Check REQUIRES functions.
5 kx ***************************************************************/
5 kx
5 kx static void __fill_provides_list( void *data, void *user_data )
5 kx {
5 kx struct package *package = (struct package *)data;
5 kx
5 kx if( package )
5 kx {
5 kx if( !check_dependencies( package ) )
5 kx {
5 kx /* move independed package to the provides list */
5 kx packages = dlist_remove( packages, (const void *)data );
5 kx provides = dlist_append( provides, (void *)package );
5 kx }
5 kx }
5 kx }
5 kx
5 kx
5 kx static void __print_extern_package( void *data, void *user_data )
5 kx {
5 kx FILE *output = (FILE *)user_data;
5 kx struct pkg *pkg = (struct pkg *)data;
5 kx
5 kx if( pkg )
5 kx {
5 kx if( pkg->group ) { fprintf( output, "# required: %s/%s=%s\n", pkg->group, pkg->name, pkg->version ); }
5 kx else { fprintf( output, "# required: %s=%s\n", pkg->name, pkg->version ); }
5 kx }
5 kx }
5 kx
5 kx static void __print_provided_package( void *data, void *user_data )
5 kx {
5 kx FILE *output = (FILE *)user_data;
5 kx struct package *package = (struct package *)data;
5 kx
5 kx if( package )
5 kx {
5 kx fprintf( output, "%s:", package->pkginfo->name );
5 kx fprintf( output, "%s:", package->pkginfo->version );
5 kx fprintf( output, "%s:", package->pkginfo->short_description );
5 kx if( package->tarball )
5 kx {
5 kx fprintf( output, "%s:", package->tarball );
5 kx }
5 kx else
5 kx {
5 kx if( package->pkginfo->group ) fprintf( output, "%s/", package->pkginfo->group );
5 kx
5 kx fprintf( output, "%s-", package->pkginfo->name );
5 kx fprintf( output, "%s-", package->pkginfo->version );
5 kx fprintf( output, "%s-", package->pkginfo->arch );
5 kx fprintf( output, "%s-", package->pkginfo->distro_name );
5 kx fprintf( output, "%s.", package->pkginfo->distro_version );
5 kx fprintf( output, "%s:", tarball_suffix ); /* default is '.txz' */
5 kx }
5 kx fprintf( output, "%s:", strproc( package->procedure ) );
5 kx fprintf( output, "%s\n", strprio( package->priority, 0 ) );
5 kx }
5 kx }
5 kx
5 kx
5 kx static void __reduce_packages_list( struct pkg *pkg )
5 kx {
5 kx struct package *package = NULL;
5 kx struct dlist *found = NULL;
5 kx
5 kx if( !pkg ) return;
5 kx
5 kx found = dlist_find_data( packages, __compare_provided, (const void *)pkg );
5 kx if( found && found->data )
5 kx {
5 kx struct dlist *list = NULL, *next = NULL;
5 kx
5 kx package = (struct package *)found->data;
5 kx
5 kx packages = dlist_remove( packages, (const void *)package );
5 kx provides = dlist_append( provides, (void *)package );
5 kx
5 kx if( !(list = package->requires->list) ) return;
5 kx
5 kx while( list )
5 kx {
5 kx next = dlist_next( list );
5 kx {
5 kx __reduce_packages_list( (struct pkg *)list->data );
5 kx }
5 kx list = next;
5 kx }
5 kx }
5 kx }
5 kx
5 kx static void __reduce_packages_list_single( void *data, void *user_data )
5 kx {
5 kx struct pkg *pkg = (struct pkg *)data;
5 kx
5 kx if( pkg ) { __reduce_packages_list( pkg ); }
5 kx }
5 kx
5 kx
5 kx static void reduce_packages_list( struct dlist *srcpkgs )
5 kx {
5 kx if( ! srcpkgs ) return;
5 kx
5 kx dlist_foreach( srcpkgs, __reduce_packages_list_single, NULL );
5 kx
5 kx dlist_free( packages, __package_free_func );
5 kx if( dlist_length( provides ) != 0 )
5 kx {
5 kx packages = provides;
5 kx provides = NULL;
5 kx }
5 kx }
5 kx
5 kx int create_provides_list( struct dlist *srcpkgs )
5 kx {
5 kx int ret = 0;
5 kx
5 kx if( !packages ) return ret;
5 kx
5 kx if( srcpkgs && dlist_length( srcpkgs ) > 0 )
5 kx {
5 kx /******************************************************************
5 kx Reduce packages list to the list of requires of source packages:
5 kx */
5 kx reduce_packages_list( srcpkgs );
5 kx }
5 kx
5 kx /* Fill two lists: provides and extern_requires: */
5 kx dlist_foreach( packages, __fill_extern_requires, NULL );
5 kx
5 kx /* Remove packages from extern_requires list which present in the provides list: */
5 kx dlist_foreach( provides, __clean_extern_requires, NULL );
5 kx
5 kx /* Now we don't need previous contents of provides list: */
5 kx dlist_free( provides, __pkg_free_func );
5 kx provides = NULL;
5 kx
5 kx /* Remove old packages if required new version of them */
5 kx remove_old_packages();
5 kx
5 kx /* move packages into provides list in order of installation: */
5 kx while( dlist_length( packages ) != 0 )
5 kx {
5 kx dlist_foreach( packages, __fill_provides_list, NULL );
5 kx }
5 kx
5 kx return dlist_length( extern_requires );
5 kx }
5 kx
5 kx void free_provides_list( void )
5 kx {
5 kx if( htmlroot ) { free( htmlroot ); htmlroot = NULL; }
5 kx if( hardware ) { free( hardware ); hardware = NULL; }
5 kx
5 kx dlist_free( extern_requires, __pkg_free_func );
5 kx dlist_free( provides, __package_free_func );
5 kx }
5 kx
5 kx void print_provides_list( const char *plist_fname )
5 kx {
5 kx FILE *plist = NULL;
5 kx
5 kx if( !plist_fname || !provides ) return;
5 kx
5 kx plist = fopen( plist_fname, "w" );
5 kx if( !plist )
5 kx {
5 kx FATAL_ERROR( "Cannot create output %s file", basename( (char *)plist_fname ) );
5 kx }
5 kx
5 kx fprintf( plist, "#\n" );
5 kx fprintf( plist, "# file format:\n" );
5 kx fprintf( plist, "# ===========\n" );
5 kx fprintf( plist, "#\n" );
5 kx fprintf( plist, "# Each line contains six fields separated by colon symbol ':' like following.\n" );
5 kx fprintf( plist, "#\n" );
5 kx fprintf( plist, "# pkgname:version:description:tarball:procedure:priority\n" );
5 kx fprintf( plist, "#\n" );
5 kx fprintf( plist, "# where:\n" );
5 kx fprintf( plist, "#\n" );
5 kx fprintf( plist, "# pkgname - should be the same as the value of pkgname in the '.DESCRIPTION' file;\n" );
5 kx fprintf( plist, "# version - package version for showing in check list dialog box if this file is\n" );
5 kx fprintf( plist, "# used to complete common check dialog for installing group of packages;\n" );
5 kx fprintf( plist, "# description - short description for showing in check list dialog box if this file is\n" );
5 kx fprintf( plist, "# used to complete common check dialog for installing group of packages;\n" );
5 kx fprintf( plist, "# tarball - should end in '.txz';\n" );
5 kx fprintf( plist, "# procedure - installation procedure {install | update}:\n" );
5 kx fprintf( plist, "# * 'install' - if package requires normal installation,\n" );
5 kx fprintf( plist, "# * 'update' - if already installed package should be updated by this\n" );
5 kx fprintf( plist, "# package archive;\n" );
5 kx fprintf( plist, "# priority - { REQUIRED|RECOMMENDED|OPTIONAL|SKIP }\n" );
5 kx fprintf( plist, "# synonims:\n" );
5 kx fprintf( plist, "# { REQUIRED | required | REQ | req }\n" );
5 kx fprintf( plist, "# { RECOMMENDED | recommended | REC | rec }\n" );
5 kx fprintf( plist, "# { OPTIONAL | optional | OPT | opt }\n" );
5 kx fprintf( plist, "# { SKIP | skip | SKP | skp }\n" );
5 kx fprintf( plist, "#\n" );
5 kx
5 kx if( extern_requires )
5 kx {
5 kx dlist_foreach( extern_requires, __print_extern_package, plist );
5 kx fprintf( plist, "#\n" );
5 kx }
5 kx dlist_foreach( provides, __print_provided_package, plist );
5 kx
5 kx fflush( plist );
5 kx fclose( plist );
5 kx }
5 kx
5 kx
5 kx /***************************************************************
5 kx Requires TREE functions:
5 kx */
5 kx
5 kx struct _ctx
5 kx {
5 kx FILE *output;
5 kx int index, size, depth;
5 kx };
5 kx
5 kx /**************************
5 kx HTML Template Variables:
5 kx */
5 kx static char *root = NULL;
5 kx static char *bug_url = NULL;
5 kx
5 kx static int svg_width = 2;
5 kx static int svg_height = 2;
5 kx
5 kx static char *json_pkgs_file = NULL;
5 kx static char *json_tree_file = NULL;
5 kx
5 kx static char *copying = "Radix cross Linux";
5 kx
5 kx #define max(a,b) ({ typeof (a) _a = (a); typeof (b) _b = (b); _a > _b ? _a : _b; })
5 kx
5 kx /*
5 kx формирование имен файлов для вывода REQUIRES tree:
5 kx
5 kx json_fname | last argument of make-pkglist | last argument type
5 kx -------------------------+-------------------------------+--------------------
5 kx './a.txt' | a.txt | regular file
5 kx './a.json' | a.json | regular file
5 kx './.json' | .json | regular file
5 kx './khadas-vim.json' | . | directory
5 kx './tmp/khadas-vim.json' | tmp | directory
5 kx -------------------------+-------------------------------+--------------------
5 kx
5 kx - если есть основное базовое имя файла и расширение, то расширение
5 kx заменяем на: '.pkgs.json', '.tree.json', '.tree.html';
5 kx
5 kx - если есть основное базовое имя файла без расширения, то добавляем
5 kx расширение: '.pkgs.json', '.tree.json', '.tree.html';
5 kx
5 kx - если основное базовое имя файла начинается с точки, то расширение
5 kx заменяем на: 'pkgs.json', 'tree.json', 'tree.html'.
5 kx */
5 kx static void allocate_fnames( const char *json_fname )
5 kx {
5 kx char *p, *e, *f = NULL;
5 kx char *buf = NULL;
5 kx
5 kx buf = (char *)malloc( (size_t)PATH_MAX );
5 kx if( !buf ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)buf, PATH_MAX );
5 kx
5 kx (void)sprintf( &buf[0], "%s", json_fname );
5 kx p = rindex( (const char *)&buf[0], '/' );
5 kx if( p )
5 kx {
5 kx if( p != &buf[0] ) f = ++p;
5 kx else f = &buf[0];
5 kx }
5 kx e = rindex( (const char *)f, '.' );
5 kx if( e )
5 kx {
5 kx if( e != f )
5 kx {
5 kx (void)sprintf( e, ".pkgs.json" ); pkgs_fname = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( e, ".tree.json" ); tree_fname = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( e, ".tree.html" ); html_fname = xstrdup( (const char *)&buf[0] );
5 kx
5 kx (void)sprintf( e, ".pkgs.min.json" ); pkgs_min_fname = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( e, ".tree.min.json" ); tree_min_fname = xstrdup( (const char *)&buf[0] );
5 kx }
5 kx else
5 kx {
5 kx (void)sprintf( e, "pkgs.json" ); pkgs_fname = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( e, "tree.json" ); tree_fname = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( e, "tree.html" ); html_fname = xstrdup( (const char *)&buf[0] );
5 kx
5 kx (void)sprintf( e, "pkgs.min.json" ); pkgs_min_fname = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( e, "tree.min.json" ); tree_min_fname = xstrdup( (const char *)&buf[0] );
5 kx }
5 kx }
5 kx else
5 kx {
5 kx e = f + strlen( f );
5 kx
5 kx (void)sprintf( e, ".pkgs.json" ); pkgs_fname = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( e, ".tree.json" ); tree_fname = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( e, ".tree.html" ); html_fname = xstrdup( (const char *)&buf[0] );
5 kx
5 kx (void)sprintf( e, ".pkgs.min.json" ); pkgs_min_fname = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( e, ".tree.min.json" ); tree_min_fname = xstrdup( (const char *)&buf[0] );
5 kx }
5 kx
5 kx if( minimize )
5 kx {
5 kx json_pkgs_file = xstrdup( (const char *)basename( pkgs_min_fname ) );
5 kx json_tree_file = xstrdup( (const char *)basename( tree_min_fname ) );
5 kx }
5 kx else
5 kx {
5 kx json_pkgs_file = xstrdup( (const char *)basename( pkgs_fname ) );
5 kx json_tree_file = xstrdup( (const char *)basename( tree_fname ) );
5 kx }
5 kx
5 kx free( buf );
5 kx }
5 kx
5 kx
5 kx /*******************************************************************
5 kx find_pkg():
5 kx ----------
5 kx Returns package found in packages list coresponded to pkg.
5 kx */
5 kx static struct package *find_pkg( struct dlist *list, struct pkg *pkg )
5 kx {
5 kx struct package *package = NULL;
5 kx struct dlist *found = NULL;
5 kx
5 kx if( !pkg ) return package;
5 kx
5 kx found = dlist_find_data( list, __compare_provided, (const void *)pkg );
5 kx if( found )
5 kx {
5 kx return (struct package *)found->data;
5 kx }
5 kx
5 kx return package;
5 kx }
5 kx
5 kx /*******************************************************************
5 kx find_package():
5 kx --------------
5 kx Returns package found in packages list coresponded to package.
5 kx */
5 kx static struct package *find_package( struct dlist *list, struct package *pkg )
5 kx {
5 kx struct package *package = NULL;
5 kx struct dlist *found = NULL;
5 kx
5 kx if( !pkg ) return package;
5 kx
5 kx found = dlist_find_data( list, __compare_packages, (const void *)pkg );
5 kx if( found )
5 kx {
5 kx return (struct package *)found->data;
5 kx }
5 kx
5 kx return package;
5 kx }
5 kx
5 kx static void __print_package_data( FILE *output, struct package *package )
5 kx {
5 kx if( !output || !package ) return;
5 kx
5 kx /* "id": "net:bind-9.10.1", */
5 kx if( package->pkginfo->group ) {
5 kx fprintf( output, " \"id\": \"%s:%s-%s\",\n", package->pkginfo->group,
5 kx package->pkginfo->name,
5 kx package->pkginfo->version );
5 kx } else {
5 kx fprintf( output, " \"id\": \"%s-%s\",\n", package->pkginfo->name,
5 kx package->pkginfo->version );
5 kx }
5 kx /* "name": "bind", */
5 kx fprintf( output, " \"name\": \"%s\",\n", package->pkginfo->name );
5 kx /* "version": "9.10.1", */
5 kx fprintf( output, " \"version\": \"%s\",\n", package->pkginfo->version );
5 kx /* "group": "net", */
5 kx if( package->pkginfo->group ) {
5 kx fprintf( output, " \"group\": \"%s\",\n", package->pkginfo->group );
5 kx } else {
5 kx fprintf( output, " \"group\": \"\",\n" );
5 kx }
5 kx /* "arch": "omap543x-eglibc", */
5 kx fprintf( output, " \"arch\": \"%s\",\n", package->pkginfo->arch );
5 kx /* "hardware": "omap5uevm", */
5 kx fprintf( output, " \"hardware\": \"%s\",\n", hardware );
5 kx /* "license": "custom", */
5 kx fprintf( output, " \"license\": \"%s\",\n", package->pkginfo->license );
5 kx /* "description": "bind 9.10.1 (DNS server and utilities)", */
5 kx fprintf( output, " \"description\": \"%s %s (%s)\",\n", package->pkginfo->name,
5 kx package->pkginfo->version,
5 kx package->pkginfo->short_description );
5 kx /* "uncompressed_size": "17M", */
5 kx fprintf( output, " \"uncompressed_size\": \"" );
5 kx if( package->pkginfo->uncompressed_size > 1048576 ) {
5 kx fprintf( output, "%ldG\",\n", package->pkginfo->uncompressed_size / 1048576 );
5 kx } else if( package->pkginfo->uncompressed_size > 1024 ) {
5 kx fprintf( output, "%ldM\",\n", package->pkginfo->uncompressed_size / 1024 );
5 kx } else {
5 kx fprintf( output, "%ldK\",\n", package->pkginfo->uncompressed_size );
5 kx }
5 kx /* "total_files": "421" */
5 kx fprintf( output, " \"total_files\": \"%d\"\n", package->pkginfo->total_files );
5 kx }
5 kx
5 kx static void __print_pkgs_node( void *data, void *user_data )
5 kx {
5 kx struct package *package = (struct package *)data;
5 kx struct _ctx *ctx = (struct _ctx *)user_data;
5 kx
5 kx if( !package || !ctx ) return;
5 kx
5 kx if( ctx->index != 0 )
5 kx {
5 kx fprintf( ctx->output, " },\n {\n" );
5 kx }
5 kx __print_package_data( ctx->output, package );
5 kx ++ctx->index;
5 kx }
5 kx
5 kx static void print_pkgs_json( FILE *output, struct dlist *list )
5 kx {
5 kx struct _ctx ctx;
5 kx
5 kx if( !output ) return;
5 kx
5 kx bzero( (void *)&ctx, sizeof(struct _ctx) );
5 kx
5 kx ctx.output = output;
5 kx ctx.index = 0;
5 kx
5 kx fprintf( output, "[{\n" );
5 kx
5 kx dlist_foreach( list, __print_pkgs_node, (void *)&ctx );
5 kx
5 kx fprintf( output, " }]\n" );
5 kx }
5 kx
5 kx static void __remove_required_package( void *data, void *user_data )
5 kx {
5 kx struct package *package = NULL;
5 kx struct pkg *pkg = (struct pkg *)data;
5 kx
5 kx if( pkg )
5 kx {
5 kx package = find_pkg( tree, pkg );
5 kx if( package )
5 kx {
5 kx /*******************************************
5 kx if package reqired for some other package
5 kx we have to remove it from tree list:
5 kx */
5 kx tree = dlist_remove_data( tree, __compare_packages, NULL, (const void *)package );
5 kx }
5 kx }
5 kx }
5 kx
5 kx static void __remove_required_packages( void *data, void *user_data )
5 kx {
5 kx struct package *package = (struct package *)data;
5 kx struct dlist *list = NULL;
5 kx
5 kx if( !package ) return;
5 kx
5 kx if( !(list = package->requires->list) ) return;
5 kx
5 kx dlist_foreach( list, __remove_required_package, NULL );
5 kx }
5 kx
5 kx static void remove_required_packages( struct dlist *list )
5 kx {
5 kx dlist_foreach( list, __remove_required_packages, NULL );
5 kx }
5 kx
5 kx
5 kx static void __check_pkg_requires( void *data, void *user_data )
5 kx {
5 kx struct pkg *pkg = (struct pkg *)data;
5 kx int *counter = (int *)user_data;
5 kx
5 kx if( pkg )
5 kx {
5 kx struct package *package = find_pkg( provides, pkg );
5 kx if( package ) { ++(*counter); }
5 kx }
5 kx }
5 kx
5 kx static int check_pkg_requires( struct dlist *list )
5 kx {
5 kx int cnt = 0;
5 kx dlist_foreach( list, __check_pkg_requires, (void *)&cnt );
5 kx return cnt;
5 kx }
5 kx
5 kx
5 kx /***************************************************************
5 kx Sort Requires Tree functions:
5 kx ----------------------------
5 kx
5 kx NOTE:
5 kx Requires sorted in reverse installation order according to
5 kx provides list.
5 kx */
5 kx
5 kx static int __install_pkg_index( struct dlist *list, struct pkg *pkg )
5 kx {
5 kx int index = -1;
5 kx
5 kx if( !pkg ) return index;
5 kx
5 kx if( list )
5 kx {
5 kx struct package *package = find_pkg( list, pkg );
5 kx
5 kx index = dlist_index( list, package );
5 kx }
5 kx
5 kx return index;
5 kx }
5 kx
5 kx static int __install_package_index( struct dlist *list, struct package *package )
5 kx {
5 kx int index = -1;
5 kx
5 kx if( !package ) return index;
5 kx
5 kx if( list )
5 kx index = dlist_index( list, package );
5 kx
5 kx return index;
5 kx }
5 kx
5 kx static int __compare_pkg_order( const void *a, const void *b )
5 kx {
5 kx int ret = 0;
5 kx int ia = -1, ib = -1;
5 kx
5 kx ia = __install_pkg_index( provides, (struct pkg *)a );
5 kx ib = __install_pkg_index( provides, (struct pkg *)b );
5 kx
5 kx if( ia < ib ) ret = -1;
5 kx if( ia > ib ) ret = 1;
5 kx
5 kx return ret;
5 kx }
5 kx
5 kx static int __compare_package_order( const void *a, const void *b )
5 kx {
5 kx int ret = 0;
5 kx int ia = -1, ib = -1;
5 kx
5 kx ia = __install_package_index( provides, (struct package *)a );
5 kx ib = __install_package_index( provides, (struct package *)b );
5 kx
5 kx if( ia < ib ) ret = -1;
5 kx if( ia > ib ) ret = 1;
5 kx
5 kx return ret;
5 kx }
5 kx
5 kx static void __sort_requires( void *data, void *user_data )
5 kx {
5 kx struct package *package = (struct package *)data;
5 kx struct dlist *reqs = NULL;
5 kx
5 kx if( !package ) return;
5 kx
5 kx if( (reqs = package->requires->list) && check_pkg_requires( reqs ) > 0 )
5 kx {
5 kx package->requires->list = reqs = dlist_sort( reqs, __compare_pkg_order );
5 kx }
5 kx }
5 kx
5 kx static struct dlist *sort_requires_tree( struct dlist *list )
5 kx {
5 kx int lenght = 0;
5 kx
5 kx if( !list ) return list;
5 kx
5 kx lenght = dlist_length( list );
5 kx
5 kx if( lenght > 1 )
5 kx list = dlist_sort( list, __compare_package_order );
5 kx
5 kx return list;
5 kx }
5 kx
5 kx static void sort_requires( struct dlist *list )
5 kx {
5 kx int lenght = 0;
5 kx
5 kx if( !list ) return;
5 kx
5 kx dlist_foreach( list, __sort_requires, NULL );
5 kx }
5 kx /*
5 kx End of Sort Requires Tree functions:
5 kx ***************************************************************/
5 kx
5 kx /***************************************************************
5 kx Binary Tree functions:
5 kx ---------------------
5 kx */
5 kx static struct dlist *pkgs = NULL;
5 kx static struct btree *btree = NULL;
5 kx
5 kx static struct pkg *duplicate_pkg( struct package *package )
5 kx {
5 kx struct pkg *pkg = NULL;
5 kx
5 kx if( !package ) return pkg;
5 kx
5 kx pkg = pkg_alloc();
5 kx pkg->name = xstrdup( (const char *)package->pkginfo->name );
5 kx pkg->group = xstrdup( (const char *)package->pkginfo->group );
5 kx pkg->version = xstrdup( (const char *)package->pkginfo->version );
5 kx pkg->procedure = package->procedure;
5 kx
5 kx return pkg;
5 kx }
5 kx
5 kx static void __fill_pkgs_list( void *data, void *user_data )
5 kx {
5 kx struct package *package = (struct package *)data;
5 kx struct pkg *pkg = NULL;
5 kx
5 kx if( !package ) return;
5 kx
5 kx pkg = duplicate_pkg( package );
5 kx pkgs = dlist_append( pkgs, (void *)pkg );
5 kx }
5 kx
5 kx /*******************************************
5 kx create_pkgs_list():
5 kx ------------------
5 kx Creates pkgs list from provides list.
5 kx */
5 kx static void create_pkgs_list( struct dlist *list )
5 kx {
5 kx if( !list ) return;
5 kx
5 kx dlist_foreach( list, __fill_pkgs_list, NULL );
5 kx }
5 kx
5 kx static void free_pkgs_list()
5 kx {
5 kx if( pkgs )
5 kx {
5 kx dlist_free( pkgs, __pkg_free_func );
5 kx pkgs = NULL;
5 kx }
5 kx }
5 kx
5 kx static int __compare_pkg( const void *a, const void *b )
5 kx {
5 kx int ret = -1;
5 kx
5 kx struct pkg *pkg1 = (struct pkg *)a;
5 kx struct pkg *pkg2 = (struct pkg *)b;
5 kx
5 kx if( pkg1->group && pkg2->group )
5 kx {
5 kx ret = strcmp( pkg1->group, pkg2->group );
5 kx }
5 kx else if( !pkg1->group && !pkg2->group )
5 kx {
5 kx ret = 0;
5 kx }
5 kx else if( pkg1->group )
5 kx {
5 kx ret = 1;
5 kx }
5 kx
5 kx if( ! ret )
5 kx {
5 kx return strcmp( pkg1->name, pkg2->name );
5 kx }
5 kx return ret;
5 kx }
5 kx
5 kx static struct pkg *__find_pkg( struct dlist *list, struct pkg *package )
5 kx {
5 kx struct pkg *pkg = NULL;
5 kx struct dlist *found = NULL;
5 kx
5 kx if( !package ) return pkg;
5 kx
5 kx found = dlist_find_data( list, __compare_pkg, (const void *)package );
5 kx if( found )
5 kx {
5 kx return (struct pkg *)found->data;
5 kx }
5 kx
5 kx return pkg;
5 kx }
5 kx
5 kx static int __compare_pkg_with_package( const void *a, const void *b )
5 kx {
5 kx int ret = -1;
5 kx
5 kx struct pkg *pkg1 = (struct pkg *)a;
5 kx struct package *pkg2 = (struct package *)b;
5 kx
5 kx if( pkg1->group && pkg2->pkginfo->group )
5 kx {
5 kx ret = strcmp( pkg1->group, pkg2->pkginfo->group );
5 kx }
5 kx else if( !pkg1->group && !pkg2->pkginfo->group )
5 kx {
5 kx ret = 0;
5 kx }
5 kx else if( pkg2->pkginfo->group )
5 kx {
5 kx ret = 1;
5 kx }
5 kx
5 kx if( ! ret )
5 kx {
5 kx return strcmp( pkg1->name, pkg2->pkginfo->name );
5 kx }
5 kx return ret;
5 kx }
5 kx
5 kx static struct pkg *__find_pkg_by_package( struct dlist *list, struct package *package )
5 kx {
5 kx struct pkg *pkg = NULL;
5 kx struct dlist *found = NULL;
5 kx
5 kx if( !package ) return pkg;
5 kx
5 kx found = dlist_find_data( list, __compare_pkg_with_package, (const void *)package );
5 kx if( found )
5 kx {
5 kx return (struct pkg *)found->data;
5 kx }
5 kx
5 kx return pkg;
5 kx }
5 kx
5 kx static struct pkg *__find_pkg_by_pkg( struct dlist *list, struct pkg *package )
5 kx {
5 kx struct pkg *pkg = NULL;
5 kx struct dlist *found = NULL;
5 kx
5 kx if( !package ) return pkg;
5 kx
5 kx found = dlist_find_data( list, __compare_pkg, (const void *)package );
5 kx if( found )
5 kx {
5 kx return (struct pkg *)found->data;
5 kx }
5 kx
5 kx return pkg;
5 kx }
5 kx
5 kx static void __btree_add_requires( struct btree *tree );
5 kx
5 kx static struct btree *__btree_add_left( void *data, void *user_data )
5 kx {
5 kx struct btree *tree = (struct btree *)user_data;
5 kx struct pkg *left = (struct pkg *)data;
5 kx struct pkg *pkg = NULL;
5 kx struct btree *node = NULL;
5 kx
5 kx if( !tree || !left ) return node;
5 kx
5 kx pkg = __find_pkg_by_pkg( pkgs, left );
5 kx
5 kx node = btree_insert_left( tree, __btree_alloc( (void *)pkg ) );
5 kx __btree_add_requires( node );
5 kx
5 kx return node;
5 kx }
5 kx
5 kx static void __btree_add_right( void *data, void *user_data )
5 kx {
5 kx struct btree *tree = *((struct btree **)user_data);
5 kx struct pkg *right = (struct pkg *)data;
5 kx struct pkg *pkg = NULL;
5 kx struct btree *node = NULL;
5 kx
5 kx if( !tree || !right ) return;
5 kx
5 kx pkg = __find_pkg_by_pkg( pkgs, right );
5 kx
5 kx node = btree_insert_right( tree, __btree_alloc( (void *)pkg ) );
5 kx __btree_add_requires( node );
5 kx
5 kx *((struct btree **)user_data) = node;
5 kx }
5 kx
5 kx static void __btree_add_requires( struct btree *tree )
5 kx {
5 kx struct package *package = NULL;
5 kx
5 kx if( !tree ) return;
5 kx
5 kx package = find_pkg( provides, (struct pkg *)tree->data );
5 kx if( package )
5 kx {
5 kx struct dlist *list = NULL;
5 kx
5 kx if( (list = package->requires->list) )
5 kx {
5 kx struct pkg *pkg = NULL;
5 kx struct btree *node = NULL;
5 kx
5 kx pkg = __find_pkg_by_pkg( pkgs, (struct pkg *)list->data );
5 kx
5 kx node = __btree_add_left( (void *)pkg, (void *)tree );
5 kx
5 kx if( dlist_length( list ) > 1 )
5 kx {
5 kx dlist_foreach( list->next, __btree_add_right, (void *)&node );
5 kx }
5 kx }
5 kx }
5 kx }
5 kx
5 kx static void __fill_btree( void *data, void *user_data )
5 kx {
5 kx struct btree *tree = *((struct btree **)user_data);
5 kx struct package *package = (struct package *)data;
5 kx struct pkg *pkg = NULL;
5 kx struct btree *node = NULL;
5 kx
5 kx if( !tree || !package ) return;
5 kx
5 kx pkg = __find_pkg_by_package( pkgs, package );
5 kx
5 kx node = btree_insert_right( tree, __btree_alloc( (void *)pkg ) );
5 kx __btree_add_requires( node );
5 kx
5 kx *((struct btree **)user_data) = node;
5 kx }
5 kx
5 kx /*******************************************************************
5 kx __print_btree_pkg():
5 kx -------------------
5 kx Print out package "group/name-version". Used for debuging only.
5 kx */
5 kx static void __print_btree_pkg( void *data, void *user_data )
5 kx {
5 kx struct pkg *pkg = (struct pkg *)data;
5 kx
5 kx if( !pkg ) return;
5 kx
5 kx fprintf( stdout, "%s/%s-%s\n", pkg->group, pkg->name, pkg->version );
5 kx }
5 kx
5 kx /*****************************************************************
5 kx __print_btree_node():
5 kx --------------------
5 kx Print out package in JSON format. Used by btree_print_json().
5 kx */
5 kx static void __print_btree_node( void *data, void *user_data )
5 kx {
5 kx struct pkg *pkg = (struct pkg *)data;
5 kx struct _bctx *ctx = (struct _bctx *)user_data;
5 kx
5 kx char *p, buf[PATH_MAX*2];
5 kx int depth = 0, max_depth = PATH_MAX + PATH_MAX / 2;
5 kx
5 kx if( !pkg || !ctx ) return;
5 kx
5 kx buf[0] = ' ';
5 kx buf[1] = '\0';
5 kx
5 kx p = (char *)&buf[1];
5 kx depth = ctx->indent;
5 kx
5 kx if( depth < 1 ) depth = 0;
5 kx if( depth > max_depth ) depth = max_depth;
5 kx
5 kx while( depth )
5 kx {
5 kx (void)sprintf( p, " " ); --depth; ++p; *p = '\0';
5 kx }
5 kx
5 kx if( pkg->group )
5 kx (void)sprintf( p, "\"name\": \"%s:%s-%s\"", pkg->group,
5 kx pkg->name,
5 kx pkg->version );
5 kx else
5 kx (void)sprintf( p, "\"name\": \"%s-%s\"", pkg->name,
5 kx pkg->version );
5 kx
5 kx fprintf( ctx->output, (char *)&buf[0] );
5 kx }
5 kx
5 kx static int __width_factor( int width )
5 kx {
5 kx double w, x = (double)width;
5 kx
5 kx if( width < 2 ) return 48;
5 kx
5 kx if( width > 1 && width < 150 )
5 kx {
5 kx w = floor( (38.399 - 7.4262 * log( x )) + 8.0 );
5 kx
5 kx return (int)w;
5 kx }
5 kx else
5 kx {
5 kx return 8;
5 kx }
5 kx }
5 kx
5 kx /*******************************************************************
5 kx __print_btree_header():
5 kx ----------------------
5 kx Print out Binary Tree Header.
5 kx */
5 kx static void __print_btree_header( FILE *fp, struct btree *btree, struct dlist *tree )
5 kx {
5 kx struct package *package = NULL;
5 kx
5 kx if( !fp || !btree || !tree ) return;
5 kx
5 kx package = find_pkg( provides, (struct pkg *)btree->data );
5 kx
5 kx if( package )
5 kx {
5 kx char *buf = NULL;
5 kx
5 kx if( dlist_length( tree ) > 1 )
5 kx {
5 kx buf = (char *)malloc( (size_t)PATH_MAX );
5 kx if( !buf ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)buf, PATH_MAX );
5 kx
5 kx (void)sprintf( &buf[0], "%s", htmlroot );
5 kx root = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( &buf[0], "%s", package->pkginfo->url );
5 kx bug_url = xstrdup( (const char *)&buf[0] );
5 kx free( buf );
5 kx }
5 kx else
5 kx {
5 kx buf = (char *)malloc( (size_t)PATH_MAX );
5 kx if( !buf ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)buf, PATH_MAX );
5 kx
5 kx if( package->pkginfo->group )
5 kx (void)sprintf( &buf[0], "%s/%s-%s", package->pkginfo->group,
5 kx package->pkginfo->name,
5 kx package->pkginfo->version );
5 kx else
5 kx (void)sprintf( &buf[0], "%s-%s", package->pkginfo->name,
5 kx package->pkginfo->version );
5 kx
5 kx root = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( &buf[0], "%s", package->pkginfo->url );
5 kx bug_url = xstrdup( (const char *)&buf[0] );
5 kx free( buf );
5 kx }
5 kx
5 kx fprintf( fp, " \"distro\": [ \"%s\", \"%s\", \"%s\" ],\n",
5 kx package->pkginfo->distro_name,
5 kx package->pkginfo->distro_version,
5 kx package->pkginfo->url );
5 kx }
5 kx }
5 kx
5 kx
5 kx /***************************************
5 kx create_btree():
5 kx --------------
5 kx Creates btree from tree list (DAG).
5 kx */
5 kx static void create_btree( struct dlist *dag, struct dlist *install )
5 kx {
5 kx struct pkg *pkg = NULL;
5 kx struct package *package = NULL;
5 kx struct dlist *list = NULL;
5 kx struct btree *node = NULL;
5 kx
5 kx if( !dag || !install ) return;
5 kx
5 kx /* first package: */
5 kx package = (struct package *)dag->data;
5 kx pkg = __find_pkg_by_package( pkgs, package );
5 kx
5 kx node = btree = __btree_alloc( (void *)pkg );
5 kx
5 kx __btree_add_requires( node );
5 kx
5 kx if( dlist_length( dag ) > 1 )
5 kx dlist_foreach( dag->next, __fill_btree, (void *)&node );
5 kx
5 kx btree_reduce( btree, __compare_pkg, NULL );
5 kx }
5 kx /*
5 kx End of Binary Tree functions:
5 kx ***************************************************************/
5 kx
5 kx
5 kx /***************************************************************
5 kx Print json format of DAG functions:
5 kx */
5 kx static void __print_pkg_tree( struct _ctx *ctx, struct dlist *list )
5 kx {
5 kx struct dlist *next = NULL;
5 kx
5 kx if( !ctx || !list ) return;
5 kx
5 kx ctx->depth += 2;
5 kx svg_width = max( svg_width, ctx->depth );
5 kx
5 kx while( list )
5 kx {
5 kx next = dlist_next( list );
5 kx {
5 kx struct pkg *pkg = (struct pkg *)list->data;
5 kx struct package *package = find_pkg( provides, pkg );
5 kx
5 kx if( package )
5 kx {
5 kx char *p, *buf = NULL;
5 kx int depth = 0;
5 kx
5 kx struct dlist *reqs = NULL;
5 kx
5 kx buf = (char *)malloc( (size_t)PATH_MAX );
5 kx if( !buf ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)buf, PATH_MAX );
5 kx
5 kx buf[0] = ' ';
5 kx buf[1] = '\0';
5 kx
5 kx p = (char *)&buf[1];
5 kx depth = ctx->depth;
5 kx
5 kx while( depth ) { (void)sprintf( p, " " ); --depth; ++p; *p = '\0'; }
5 kx
5 kx (void)sprintf( p - 1, "{\n" );
5 kx fprintf( ctx->output, (char *)&buf[0] );
5 kx *(p - 1) = ' '; *p = '\0';
5 kx
5 kx if( pkg->group )
5 kx (void)sprintf( p, "\"name\": \"%s:%s-%s\"", pkg->group,
5 kx pkg->name,
5 kx pkg->version );
5 kx else
5 kx (void)sprintf( p, "\"name\": \"%s-%s\"", pkg->name,
5 kx pkg->version );
5 kx
5 kx fprintf( ctx->output, (char *)&buf[0] );
5 kx
5 kx if( (reqs = package->requires->list) && check_pkg_requires( reqs ) > 0 )
5 kx {
5 kx fprintf( ctx->output, ",\n" );
5 kx
5 kx (void)sprintf( p, "\"children\": [\n" );
5 kx fprintf( ctx->output, (char *)&buf[0] );
5 kx
5 kx __print_pkg_tree( ctx, reqs );
5 kx
5 kx (void)sprintf( p, "]\n" );
5 kx fprintf( ctx->output, (char *)&buf[0] );
5 kx }
5 kx else
5 kx {
5 kx fprintf( ctx->output, "\n" );
5 kx }
5 kx
5 kx (void)sprintf( p - 1, "}" );
5 kx fprintf( ctx->output, (char *)&buf[0] );
5 kx *(p - 1) = ' '; *p = '\0';
5 kx
5 kx if( next ) { fprintf( ctx->output, ",\n" ); }
5 kx else { fprintf( ctx->output, "\n" ); }
5 kx
5 kx free( buf );
5 kx } /* End if( package ) */
5 kx }
5 kx list = next;
5 kx } /* End of while( list ) */
5 kx
5 kx ctx->depth -= 2;
5 kx }
5 kx
5 kx static void __print_package_node( struct _ctx *ctx, struct package *package )
5 kx {
5 kx char *p, *buf = NULL;
5 kx int depth = 0;
5 kx
5 kx struct dlist *list = NULL;
5 kx
5 kx if( !package || !ctx ) return;
5 kx
5 kx buf = (char *)malloc( (size_t)PATH_MAX );
5 kx if( !buf ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)buf, PATH_MAX );
5 kx
5 kx buf[0] = ' ';
5 kx buf[1] = '\0';
5 kx
5 kx p = (char *)&buf[1];
5 kx depth = ctx->depth;
5 kx
5 kx while( depth ) { (void)sprintf( p, " " ); --depth; ++p; *p = '\0'; }
5 kx
5 kx (void)sprintf( p - 1, "{\n" );
5 kx fprintf( ctx->output, (char *)&buf[0] );
5 kx *(p - 1) = ' '; *p = '\0';
5 kx
5 kx if( package->pkginfo->group )
5 kx (void)sprintf( p, "\"name\": \"%s:%s-%s\"", package->pkginfo->group,
5 kx package->pkginfo->name,
5 kx package->pkginfo->version );
5 kx else
5 kx (void)sprintf( p, "\"name\": \"%s-%s\"", package->pkginfo->name,
5 kx package->pkginfo->version );
5 kx
5 kx fprintf( ctx->output, (char *)&buf[0] );
5 kx
5 kx if( (list = package->requires->list) && check_pkg_requires( list ) > 0 )
5 kx {
5 kx fprintf( ctx->output, ",\n" );
5 kx
5 kx (void)sprintf( p, "\"children\": [\n" );
5 kx fprintf( ctx->output, (char *)&buf[0] );
5 kx
5 kx __print_pkg_tree( ctx, list );
5 kx
5 kx (void)sprintf( p, "]\n" );
5 kx fprintf( ctx->output, (char *)&buf[0] );
5 kx }
5 kx else
5 kx {
5 kx fprintf( ctx->output, "\n" );
5 kx }
5 kx
5 kx (void)sprintf( p - 1, "}" );
5 kx fprintf( ctx->output, (char *)&buf[0] );
5 kx *(p - 1) = ' '; *p = '\0';
5 kx
5 kx free( buf );
5 kx }
5 kx
5 kx static void __print_tree_node( void *data, void *user_data )
5 kx {
5 kx struct package *package = (struct package *)data;
5 kx struct _ctx *ctx = (struct _ctx *)user_data;
5 kx
5 kx if( !package || !ctx ) return;
5 kx
5 kx if( ctx->size > 1 )
5 kx {
5 kx if( ctx->index == 0 )
5 kx {
5 kx char *buf = NULL;
5 kx
5 kx buf = (char *)malloc( (size_t)PATH_MAX );
5 kx if( !buf ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)buf, PATH_MAX );
5 kx
5 kx (void)sprintf( &buf[0], "%s", htmlroot );
5 kx root = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( &buf[0], "%s", package->pkginfo->url );
5 kx bug_url = xstrdup( (const char *)&buf[0] );
5 kx free( buf );
5 kx
5 kx fprintf( ctx->output, " \"distro\": [ \"%s\", \"%s\", \"%s\" ],\n",
5 kx package->pkginfo->distro_name,
5 kx package->pkginfo->distro_version,
5 kx package->pkginfo->url );
5 kx fprintf( ctx->output, " \"name\": \"%s\",\n", htmlroot );
5 kx fprintf( ctx->output, " \"children\": [\n" );
5 kx }
5 kx
5 kx
5 kx __print_package_node( ctx, package );
5 kx svg_height += 2;
5 kx
5 kx
5 kx if( ctx->index < ctx->size - 1 ) fprintf( ctx->output, "," );
5 kx else fprintf( ctx->output, "\n ]" );
5 kx
5 kx fprintf( ctx->output, "\n" );
5 kx }
5 kx else
5 kx {
5 kx struct dlist *reqs = NULL;
5 kx char *buf = NULL;
5 kx
5 kx buf = (char *)malloc( (size_t)PATH_MAX );
5 kx if( !buf ) { FATAL_ERROR( "Cannot allocate memory" ); }
5 kx bzero( (void *)buf, PATH_MAX );
5 kx
5 kx if( package->pkginfo->group )
5 kx (void)sprintf( &buf[0], "%s/%s-%s", package->pkginfo->group,
5 kx package->pkginfo->name,
5 kx package->pkginfo->version );
5 kx else
5 kx (void)sprintf( &buf[0], "%s-%s", package->pkginfo->name,
5 kx package->pkginfo->version );
5 kx
5 kx root = xstrdup( (const char *)&buf[0] );
5 kx (void)sprintf( &buf[0], "%s", package->pkginfo->url );
5 kx bug_url = xstrdup( (const char *)&buf[0] );
5 kx free( buf );
5 kx
5 kx fprintf( ctx->output, " \"distro\": [ \"%s\", \"%s\", \"%s\" ],\n",
5 kx package->pkginfo->distro_name,
5 kx package->pkginfo->distro_version,
5 kx package->pkginfo->url );
5 kx if( package->pkginfo->group )
5 kx fprintf( ctx->output, " \"name\": \"%s:%s-%s\"", package->pkginfo->group,
5 kx package->pkginfo->name,
5 kx package->pkginfo->version );
5 kx else
5 kx fprintf( ctx->output, " \"name\": \"%s-%s\"", package->pkginfo->name,
5 kx package->pkginfo->version );
5 kx
5 kx
5 kx svg_height += 2;
5 kx ctx->depth -=2;
5 kx
5 kx if( (reqs = package->requires->list) && check_pkg_requires( reqs ) > 0 )
5 kx {
5 kx fprintf( ctx->output, ",\n" );
5 kx
5 kx fprintf( ctx->output, " \"children\": [\n" );
5 kx
5 kx __print_pkg_tree( ctx, reqs );
5 kx
5 kx fprintf( ctx->output, " ]\n" );
5 kx }
5 kx
5 kx }
5 kx
5 kx ++ctx->index;
5 kx }
5 kx
5 kx static void print_tree_json( FILE *output, struct dlist *list )
5 kx {
5 kx struct _ctx ctx;
5 kx
5 kx if( !output || !list ) return;
5 kx
5 kx bzero( (void *)&ctx, sizeof(struct _ctx) );
5 kx
5 kx ctx.output = output;
5 kx ctx.index = 0;
5 kx ctx.size = dlist_length( list );
5 kx ctx.depth = 2;
5 kx
5 kx fprintf( output, "{\n" );
5 kx dlist_foreach( list, __print_tree_node, (void *)&ctx );
5 kx fprintf( output, "}\n" );
5 kx
5 kx svg_height += svg_width / 2;
5 kx
5 kx svg_width = (svg_width + 4) * 160;
5 kx svg_height = (svg_height + 4) * 24;
5 kx }
5 kx /*
5 kx End of print json format of DAG functions.
5 kx ***************************************************************/
5 kx
5 kx #include <pkglist.html.c>
5 kx
5 kx void print_provides_tree( const char *json_fname, enum _tree_format tree_format )
5 kx {
5 kx FILE *pkgs_fp = NULL, *tree_fp = NULL, *html_fp = NULL;
5 kx
5 kx allocate_fnames( json_fname );
5 kx
5 kx pkgs_fp = fopen( (const char *)pkgs_fname, "w" );
5 kx if( !pkgs_fp ) { FATAL_ERROR( "Cannot create %s file", basename( pkgs_fname ) ); }
5 kx tree_fp = fopen( (const char *)tree_fname, "w" );
5 kx if( !tree_fp ) { FATAL_ERROR( "Cannot create %s file", basename( tree_fname ) ); }
5 kx html_fp = fopen( (const char *)html_fname, "w" );
5 kx if( !html_fp ) { FATAL_ERROR( "Cannot create %s file", basename( html_fname ) ); }
5 kx
5 kx tree = dlist_copy( provides );
5 kx
5 kx /*****************************************************
5 kx print out the array of all packages in JSON format:
5 kx */
5 kx print_pkgs_json( pkgs_fp, provides );
5 kx fflush( pkgs_fp ); fclose( pkgs_fp );
5 kx
5 kx provides = dlist_reverse( provides );
5 kx sort_requires( provides ); /* sort requires in reverse installation order */
5 kx
5 kx /********************************************************
5 kx Sort the REQUIRES TREE in reverse installation order.
5 kx */
5 kx tree = sort_requires_tree( tree );
5 kx
5 kx /********************************************************
5 kx remove unneded packages from tree list to leave the
5 kx last installation layer of packages presented in DAG:
5 kx */
5 kx remove_required_packages( provides );
5 kx
5 kx
5 kx if( tree_format == TFMT_BIN )
5 kx {
5 kx int width = 0, height = 0;
5 kx
5 kx /********************************************************************
5 kx print out the REQUIRES TREE in JSON format as reduced binary tree:
5 kx */
5 kx create_pkgs_list( provides );
5 kx create_btree( tree, provides );
5 kx
5 kx width = btree_width( btree );
5 kx height = btree_height( btree );
5 kx
5 kx svg_width = (height + 4) * 240;
5 kx svg_height = (width + 4) * __width_factor( width );
5 kx
5 kx fprintf( tree_fp, "{\n" );
5 kx __print_btree_header( tree_fp, btree, tree );
5 kx btree_print_json( tree_fp, btree, __print_btree_node );
5 kx fprintf( tree_fp, "}\n" );
5 kx
5 kx __btree_free( btree );
5 kx free_pkgs_list();
5 kx }
5 kx else
5 kx {
5 kx /****************************************************
5 kx print out the REQUIRES TREE in JSON format as DAG:
5 kx */
5 kx print_tree_json( tree_fp, tree );
5 kx }
5 kx
5 kx fflush( tree_fp ); fclose( tree_fp );
5 kx
5 kx if( minimize )
5 kx {
5 kx if( minimize_json( (const char *)pkgs_fname, (const char *)pkgs_min_fname ) < 1 )
5 kx {
5 kx (void)unlink( (const char *)pkgs_min_fname );
5 kx }
5 kx if( minimize_json( (const char *)tree_fname, (const char *)tree_min_fname ) < 1 )
5 kx {
5 kx (void)unlink( (const char *)tree_min_fname );
5 kx }
5 kx }
5 kx
5 kx
5 kx /***********************************************
5 kx print out the HTML to view REQIIRES TREE:
5 kx */
5 kx print_tree_html( html_fp );
5 kx fflush( html_fp ); fclose( html_fp );
5 kx
5 kx
5 kx /*****************
5 kx free resources:
5 kx */
5 kx if( root ) { free( root ); root = NULL; }
5 kx if( bug_url ) { free( bug_url ); bug_url = NULL; }
5 kx
5 kx if( pkgs_fname ) { free( pkgs_fname ); pkgs_fname = NULL; }
5 kx if( tree_fname ) { free( tree_fname ); tree_fname = NULL; }
5 kx if( html_fname ) { free( html_fname ); html_fname = NULL; }
5 kx
5 kx if( pkgs_min_fname ) { free( pkgs_min_fname ); pkgs_min_fname = NULL; }
5 kx if( tree_min_fname ) { free( tree_min_fname ); tree_min_fname = NULL; }
5 kx
5 kx if( json_pkgs_file ) { free( json_pkgs_file ); json_pkgs_file = NULL; }
5 kx if( json_tree_file ) { free( json_tree_file ); json_tree_file = NULL; }
5 kx
5 kx __dlist_free( tree ); /* do not free node data */
5 kx }
5 kx /*
5 kx End of Requires TREE functions.
5 kx ***************************************************************/