/* * Create a spec file object from a spec file * @param [String] filename Spec file path * @return [Spec] */ static VALUE spec_s_open(VALUE klass, VALUE filename) { #if RPM_VERSION_CODE < RPM_VERSION(4,1,0) Spec rspec; #else rpmts ts = NULL; #endif if (TYPE(filename) != T_STRING) { rb_raise(rb_eTypeError, "illegal argument type"); } #if RPM_VERSION_CODE < RPM_VERSION(4,1,0) switch (parseSpec(&rspec, RSTRING_PTR(filename), "/", NULL, 0, "", NULL, 1, 1)) { case 0: if (rspec != NULL) { break; } default: rb_raise(rb_eRuntimeError, "specfile `%s' parsing failed", RSTRING_PTR(filename)); } return Data_Wrap_Struct(klass, NULL, spec_free, rspec); #else ts = rpmtsCreate(); #if RPM_VERSION_CODE < RPM_VERSION(4,4,8) switch (parseSpec(ts, RSTRING_PTR(filename), "/", NULL, 0, "", NULL, 1, 1)) { #elif RPM_VERSION_CODE < RPM_VERSION(4,5,90) switch (parseSpec(ts, RSTRING_PTR(filename), "/", 0, "", NULL, 1, 1, 0)) { #elif RPM_VERSION_CODE < RPM_VERSION(5,0,0) switch (parseSpec(ts, RSTRING_PTR(filename), "/", NULL, 0, "", NULL, 1, 1)) { #else switch (parseSpec(ts, RSTRING_PTR(filename), "/", 0, "", NULL, 1, 1, 0)) { #endif case 0: if (ts != NULL) { break; } default: rb_raise(rb_eRuntimeError, "specfile `%s' parsing failed", RSTRING_PTR(filename)); } return Data_Wrap_Struct(klass, NULL, ts_free, ts); #endif } /* * * Alias for Spec#open */ VALUE rpm_spec_open(const char* filename) { return spec_s_open(rpm_cSpec, rb_str_new2(filename)); } /* * @return [String] Return Build root defined in the spec file */ VALUE rpm_spec_get_buildroot(VALUE spec) { #if RPM_VERSION_CODE < RPM_VERSION(4,5,90) if (RPM_SPEC(spec)->buildRootURL) { return rb_str_new2(RPM_SPEC(spec)->buildRootURL); } #elif RPM_VERSION_CODE < RPM_VERSION(4,5,90) if (RPM_SPEC(spec)->rootURL) { return rb_str_new2(RPM_SPEC(spec)->rootURL); } #elif RPM_VERSION_CODE < RPM_VERSION(5,0,0) if (RPM_SPEC(spec)->buildRoot) { return rb_str_new2(RPM_SPEC(spec)->buildRoot); } #else const char *buildRootURL = rpmGenPath(RPM_SPEC(spec)->rootURL, "%{?buildroot}", NULL); VALUE result = rb_str_new2(buildRootURL); buildRootURL = _free(buildRootURL); return result; #endif return Qnil; } /* * @return [String] Return Build subdirectory defined in the spec file */ VALUE rpm_spec_get_buildsubdir(VALUE spec) { if (RPM_SPEC(spec)->buildSubdir) { return rb_str_new2(RPM_SPEC(spec)->buildSubdir); } return Qnil; } /* * @return [Array<String>] Return Build architectures defined in the spec file */ VALUE rpm_spec_get_buildarchs(VALUE spec) { VALUE ba = rb_ivar_get(spec, id_ba); if (NIL_P(ba)) { register int i; ba = rb_ary_new(); for (i = 0; i < RPM_SPEC(spec)->BACount; i++) { rb_ary_push(ba, rb_str_new2(RPM_SPEC(spec)->BANames[i])); } rb_ivar_set(spec, id_ba, ba); } return ba; } /* * @return [Array<RPM::Require>] Return Build requires defined in the spec file */ VALUE rpm_spec_get_buildrequires(VALUE spec) { VALUE br = rb_ivar_get(spec, id_br); #if RPM_VERSION_CODE < RPM_VERSION(4,6,0) || RPM_VERSION_CODE >= RPM_VERSION(5,0,0) if (NIL_P(br)) { const char** names; const char** vers; int_32* flags; int_32 count; rpmTagType nt, vt, type; register int i; br = rb_ary_new(); if (!headerGetEntryMinMemory(RPM_SPEC(spec)->buildRestrictions, RPMTAG_REQUIRENAME, (hTYP_t)&nt, (hPTR_t*)&names, (hCNT_t)&count)) { goto leave; } get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_REQUIREVERSION, &vt, (void*)&vers); get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_REQUIREFLAGS, &type, (void*)&flags); for (i = 0; i < count; i++) { rb_ary_push(br, rpm_require_new(names[i], rpm_version_new(vers[i]), flags[i], spec)); } release_entry(nt, names); release_entry(vt, vers); rb_ivar_set(spec, id_br, br); } leave: return br; #else rpmtd nametd = rpmtdNew(); rpmtd versiontd = rpmtdNew(); rpmtd flagtd = rpmtdNew(); if (NIL_P(br)) { br = rb_ary_new(); if (!headerGet(RPM_SPEC(spec)->buildRestrictions, RPMTAG_REQUIRENAME, nametd, HEADERGET_MINMEM)) { goto leave; } get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_REQUIREVERSION, versiontd); get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_REQUIREFLAGS, flagtd); rpmtdInit(nametd); while ( rpmtdNext(nametd) != -1 ) { rb_ary_push(br, rpm_require_new(rpmtdGetString(nametd), rpm_version_new(rpmtdNextString(versiontd)), *rpmtdNextUint32(flagtd), spec)); } rb_ivar_set(spec, id_br, br); } leave: rpmtdFree(nametd); rpmtdFree(versiontd); rpmtdFree(flagtd); return br; #endif } /* * @return [Array<RPM::Conflict>] Return Build conflicts defined in the spec file */ VALUE rpm_spec_get_buildconflicts(VALUE spec) { VALUE bc = rb_ivar_get(spec, id_bc); #if RPM_VERSION_CODE < RPM_VERSION(4,6,0) || RPM_VERSION_CODE >= RPM_VERSION(5,0,0) if (NIL_P(bc)) { const char** names; const char** vers; int_32* flags; int_32 count; rpmTagType nt, vt, type; register int i; bc = rb_ary_new(); if (!headerGetEntryMinMemory(RPM_SPEC(spec)->buildRestrictions, RPMTAG_CONFLICTNAME, (hTYP_t)&nt, (hPTR_t*)&names, (hCNT_t)&count)) { goto leave; } get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_CONFLICTVERSION, &vt, (void*)&vers); get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_CONFLICTFLAGS, &type, (void*)&flags); for (i = 0; i < count; i++) { rb_ary_push(bc, rpm_conflict_new(names[i], rpm_version_new(vers[i]), flags[i], spec)); } release_entry(nt, names); release_entry(vt, vers); rb_ivar_set(spec, id_bc, bc); } leave: return bc; #else rpmtd nametd = rpmtdNew(); rpmtd versiontd = rpmtdNew(); rpmtd flagtd = rpmtdNew(); if (NIL_P(bc)) { bc = rb_ary_new(); if (!headerGet(RPM_SPEC(spec)->buildRestrictions, RPMTAG_CONFLICTNAME, nametd, HEADERGET_MINMEM)) { goto leave; } get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_CONFLICTVERSION, versiontd); get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_CONFLICTFLAGS, flagtd); rpmtdInit(nametd); while ( rpmtdNext(nametd) != -1) { rb_ary_push(bc, rpm_conflict_new(rpmtdGetString(nametd), rpm_version_new(rpmtdNextString(versiontd)), *rpmtdNextUint32(flagtd), spec)); } rb_ivar_set(spec, id_bc, bc); } leave: rpmtdFree(nametd); rpmtdFree(versiontd); rpmtdFree(flagtd); return bc; #endif }
/* * Check the dependencies. * @return [Array<Dependency>, +nil+] If dependencies are not met returns an * array with dependencies. Otherwise +nil+. */ VALUE rpm_transaction_check(VALUE trans) { #if RPM_VERSION_CODE < RPM_VERSION(4,1,0) rpmDependencyConflict conflicts; int num; rpmdepCheck(RPM_TRANSACTION(trans), &conflicts, &num); if (num) { VALUE list = rb_ary_new(); register int i; for (i = 0; i < num; i++) { VALUE dep; switch (conflicts[i].sense) { case RPMDEP_SENSE_REQUIRES: dep = rpm_require_new(conflicts[i].needsName, rpm_version_new(conflicts[i].needsVersion), conflicts[i].needsFlags, rpm_package_new_from_header(conflicts[i].byHeader)); break; case RPMDEP_SENSE_CONFLICTS: dep = rpm_conflict_new(conflicts[i].needsName, rpm_version_new(conflicts[i].needsVersion), conflicts[i].needsFlags, rpm_package_new_from_header(conflicts[i].byHeader)); break; } rb_ary_push(list, dep); } rpmdepFreeConflicts(conflicts, num); return list; } return Qnil; #else int rc; rpmps ps; int num; VALUE list = Qnil; rc = rpmtsCheck(RPM_TRANSACTION(trans)); ps = rpmtsProblems(RPM_TRANSACTION(trans)); #if RPM_VERSION_CODE < RPM_VERSION(4,9,0) || RPM_VERSION_CODE >= RPM_VERSION(5,0,0) /* get rid of duplicate problems */ rpmpsTrim(ps, RPMPROB_FILTER_NONE); #endif num = rpmpsNumProblems(ps); #ifdef RPMPS_OPAQUE rpmpsi psi = rpmpsInitIterator(ps); if (num > 0) { list = rb_ary_new(); } while (rpmpsNextIterator(psi) >= 0) { rpmProblem p = rpmpsGetProblem(psi); VALUE dep; switch (rpmProblemGetType(p)) { case RPMPROB_REQUIRES: { char *buf = strdup (rpmProblemGetAltNEVR(p)); /* TODO: zaki: NULL check*/ char *end; char *name = buf+2; char *relation = NULL; char *evr = NULL; rpmsenseFlags sense_flags = 0; end = strchr ( name, ' '); if ( end ) { *end = '\0'; relation = end + 1; end = strchr ( relation, ' '); if ( end ) { *end = '\0'; evr = end + 1; } for ( ; (*relation) != '\0'; relation++ ) { if ( (*relation) == '=' ) { sense_flags |= RPMSENSE_EQUAL; } else if ( (*relation) == '>' ) { sense_flags |= RPMSENSE_GREATER; } else if ( (*relation) == '<' ) { sense_flags |= RPMSENSE_LESS; } } } dep = rpm_require_new(name, rpm_version_new(evr ? evr : ""), sense_flags, package_new_from_NEVR( rpmProblemGetPkgNEVR(p) )); free ( buf ); rb_ary_push(list, dep); break; } default: break; } } #else if (ps != NULL && 0 < num) { rpmProblem p; int i; list = rb_ary_new(); for (i = 0; i < num; i++) { const char *altNEVR; VALUE dep; p = ps->probs + i; altNEVR = (p->altNEVR ? p->altNEVR : "? ?altNEVR?"); if (p->ignoreProblem) continue; #if 0 /* XXX shouldn't be needed at all due to rpmpsTrim() */ /* Filter already appended problems. */ for (j = 0; j < i; j++) { if (!sameProblem(p, ps->probs + j)) break; } if (j < i) continue; #endif if ( p->type == RPMPROB_REQUIRES ) { char *buf = strdup ( altNEVR ); /* TODO: zaki: NULL check*/ char *end; char *name = buf+2; char *relation = NULL; char *evr = ""; rpmsenseFlags sense_flags = 0; end = strchr ( name, ' '); if ( end ) { *end = '\0'; relation = end + 1; end = strchr ( relation, ' '); if ( end ) { *end = '\0'; evr = end + 1; } for ( ; (*relation) != '\0'; relation++ ) { if ( (*relation) == '=' ) { sense_flags |= RPMSENSE_EQUAL; } else if ( (*relation) == '>' ) { sense_flags |= RPMSENSE_GREATER; } else if ( (*relation) == '<' ) { sense_flags |= RPMSENSE_LESS; } } } dep = rpm_require_new(name, rpm_version_new(evr), sense_flags, package_new_from_NEVR(p->pkgNEVR) ); free ( buf ); rb_ary_push(list, dep); } else { #if 0 RPMPROB_CONFLICT: RPMPROB_BADARCH: RPMPROB_BADOS: RPMPROB_PKG_INSTALLED: RPMPROB_BADRELOCATE: RPMPROB_NEW_FILE_CONFLICT: RPMPROB_FILE_CONFLICT: RPMPROB_OLDPACKAGE: RPMPROB_DISKSPACE: RPMPROB_DISKNODES: RPMPROB_BADPRETRANS: #endif break; } #if 0 printf ("%d, type=%d, ignoreProblem=%d, str1=%s pkgNEVR=%s, %s\n", i, p->type, p->ignoreProblem, p->str1, p->pkgNEVR, altNEVR); #endif } } #endif /* RPMPS_OPAQUE */ ps = rpmpsFree(ps); return list; #endif }