[Aptitude-devel] Review: 1ec363ac (001.1-package^)

Daniel Burrows dburrows at debian.org
Tue Jul 20 15:26:57 UTC 2010


  Review of the package and version classes.

> +      package::package(const pkgCache::PkgIterator &_pkg)
> +	: pkg(_pkg), is_virtual(false), short_desc_fallback(_("virtual"))

  I wonder if it would be better to default-construct
short_desc_fallback (i.e., don't list it) and then assign it from
_("virtual") later, to avoid looking up _("virtual") for non-virtual
packages.  Or if you really want to avoid the default-construction,
use a ternary operator to avoid it.

> +	// name is always used during during initial sorting.
> +	// So lazy loading doesn't have sens here.

  "sense"

> +	if(!candver.end())
> +	  candidate_ver = version::create(candver);
> +	else if(pkg.CurrentVer().end() && state.Install())
> +	  candidate_ver = version::create(state.InstVerIter(*apt_cache_file));
> +	// Return the to-be-installed version
> +	else if(!pkg.CurrentVer().end())
> +	  candidate_ver = version::create(pkg.CurrentVer());
> +	else
> +	{
> +	  candidate_ver = version_ptr();
> +	  is_virtual = true;
> +	}

  Is that logic correct?  I think you should only set is_virtual if
there are no versions at all (i.e., pkg.VersionList().end() is true).

> +      package::tag_iterator package::tags_begin() const
> +      {
> +	if(is_virtual && !tags)
> +	  tags = std::set<tag>();
> +
> +	if(!tags)
> +	  tags = aptitude::apt::get_tags(pkg);
> +
> +	return (*tags).begin();
> +      }

  I'd prefer using a helper routine and cleaning up the logic:

  void package::ensure_tags() const
  {
    if(!tags)
      {
        if(is_virtual)
          tags = std::set<tag>();
        else
          tags = aptitude::apt::get_tags(pkg);
      }
  }

  package::tag_iterator package::tags_begin() const
  {
    ensure_tags();
    return (*tags).begin();
  }

  package::tag_iterator package::tags_end() const
  {
    ensure_tags();
    return (*tags).begin();
  }

  Also, I wonder if you really need to check for a virtual package
here -- I thought get_tags() was robust against that.

  Note: usually where you see if(!x) x = a; if(!x) x = b; the reason
is for robustness, because the first assignment might fail for some
reason.  I don't see that as being likely here.  Now what might be
better is something like:

  if(!tags)
    {
      try
        {
          tags = load_tags(pkg);
        }
      catch(...) // Should catch std::exception and cw::util::Exception and log.
        {
          tags = std::set<tag>();
        }
    }

  I don't think this is required here; load_tags already handles
exceptions itself.

> +      void package::load_versions() const
> +      {
> +	versions = std::vector<version_ptr>();
> +
> +	if(!is_virtual)

  Not necessary -- virtual packages by definition have no versions.

> +	  for(pkgCache::VerIterator i=pkg.VersionList(); !i.end(); i++)
> +	    if(i!=get_candidate_ver().get()->get_ver())
> +	      (*versions).push_back(version::create(i));
> +	    else
> +	      (*versions).push_back(get_candidate_ver());

  This is OK for now.  Long run, I think versions (and packages)
should be flyweights, which would make this check unnecessary.

> +      const std::string &package::get_archive() const
> +      {
> +	return is_virtual?empty_string:get_candidate_ver().get()->get_archive();
> +      }

  Could you break this line up a little more?

    return is_virtual
             ? empty_string
             : get_candidate_ver()->get_archive();

  Same for get_candidate_version().

  The reason for not caching this is presumably that the candidate
version will handle caching?

  Also, the test here is wrong: it should check whether there is a
candidate version, not whether the package is virtual.  (same goes for
other places that test is_virtual and then dereference
get_candidate_ver())

> +      const std::string &package::get_current_version() const
> +      {
> +	if(is_virtual)
> +	  return empty_string;

  I think the actual test here should be pkg.CurrentVer().end(); this
will be wrong for a non-virtual package with no current version.

> +	if(!current_version)
> +	  current_version = pkg.CurrentVer() ? pkg.CurrentVer().VerStr() : empty_string;
> +
> +	return *current_version;
> +      }

  Have you clocked an actual speedup from copying the empty string?  I
think it should be about the same as assigning from std::string().

  If you're worried about unnecessary intermediates, I think that
in_place supposedly avoids them:

using boost::in_place; // I think that's the right namespace

  if(pkg.CurrentVer()) // in_place() has different types in each branch
                       // so can't use the ternary operator.
    current_version = in_place(pkg.CurrentVer().VerStr())
  else
    current_version = in_place();

  I would personally just as soon accept the intermediary copies in
the interest of readability, but if you aren't sure, you could always
time it and see if there's a difference.  My guess is that it will be
negligible, but I've been wrong before.


  If you do go with your current code, please break the long ?: line
up as illustrated earlier.

> +      const std::string &package::get_short_description() const
> +      {
> +	return is_virtual?short_desc_fallback:get_candidate_ver().get()->get_short_description();

  As noted earlier, it would be preferable to initialize
short_desc_fallback here.

  Also, in this and other places where you use the .get()-> idiom, I'd
suggest just relying on the operator-> overload of the shared_ptr
class:

  return is_virtual
           ? short_desc_fallback // TODO: initialize this here
           : get_candidate_ver()->get_short_description();

> +namespace aptitude
> +{
> +  namespace gui
> +  {
> +    namespace qt
> +    {
> +      class package;
> +      typedef boost::shared_ptr<package> package_ptr;
> +
> +      /** \brief Package is an object representing each displayable packages.

  "An object representing a displayable package."

> +       *  It is also possible to retrieve raw PkgIterator object for this package

  "the raw PkgIterator object for this package."

> +	/** \brief Retrieve archive, which contains candidate version of this package. */

  "Retrieve the archive which contains the candidate version of this package."

> +	/** \brief Retrieve candidate version for this package. */

  "Retrieve the candidate version number of this package."

> +	/** \brief Retrieve installed version of this package. */

  "Retrieve the installed version number of this package."

> +	const std::string &get_current_version() const;

> +	/** \brief Retrieve project's homepage. */

  "Retrieve the package's homepage."

> +	/** \brief Retrieve long description of this package. */

  "Retrieve the long description of this package."

> +	/** \brief Retrieve mainatiner of this package. */

  "Retrieve the maintainer of this package." (note spelling)

> +	/** \brief Retrieve name of this package. */

  "Retrieve the name of this package."

> +	/** \brief Retrieve priority of this package. */

  +the

> +	/** \brief Retrieve section this package belongs. */

  "Retrieve the section to which this package belongs."

> +	/** \brief Retrieve short description of this package. */

  "Retrieve the short description of this package."

> +	/** \brief Retrieve name of source package for this package. */

  "Retrieve the name of this package's source package."

> +	/** \brief Retrieve a reference for PkgIterator object for this package. */

  "Retrieve the PkgIterator corresponding to this package."

> +	/** \brief Retrieve a reference to version_ptr object for candidate version
> +	   *  of this package.
> +	   */

  "Retrieve the candidate version of this package, or an invalid reference
   if the package has no candidate version."

> +      /** \todo This should spit text into a TextBuffer and use
> +       *  indentation tags to align bullets (so that paragraphs wrap
> +       *  properly).  Ideally the text of a bulleted item should align
> +       *  with the text *following* the bullet.
> +       */
> +      void version::make_desc_text(const std::vector<description_element_ref> &elements,
> +				  int level,
> +				  std::string &out) const

  Rendering logic in such a generic module raises a red flag for me.

  I suggest just caching the parsed description, and letting consumers
of this class render it.  Or, alternatively, just always re-parsing
the description and returning a new parse each time.

> +      /** \brief version is an object representing each displayable versions of package.

  "An object representing a displayable version of a package."

> +       *  It is also possible to retrieve raw VerIterator object for this version

  "It is also possible to retrieve the raw VerIterator object for this version."

> +	/** \brief Retrieve archive, which contains candidate version of this version. */

  "Retrieve a description of the archives that contain this version."

  (long-term we should probably return the archives as some sort of
   collection?)

> +	/** \brief Retrieve project's homepage. */

  "Retrieve the package's homepage."

> +	/** \brief Retrieve long description of this version. */

  "Retrieve the long description of this version."

> +	/** \brief Retrieve mainatiner of this version. */

  +the

> +	/** \brief Retrieve priority of this version. */

  +the

> +	/** \brief Retrieve short description of this version. */

  +the

> +	/** \brief Retrieve name of source package for this version. */

  "Retrieve the name of this version's source package."

> +	/** \brief Retrieve string representing this version. */

  "Retrieve the version number of this version."

> +	const std::string &get_ver_string() const;

  Suggest instead get_version_number(); and corresponding changes to
other names.

> +	/** \brief Retrieve a reference for VerIterator object for this version. */

  "Retrieve the VerIterator corresponding to this version."

  Daniel



More information about the Aptitude-devel mailing list