Martin Aspeli, on 2007-05-11:
> For the record, I really don't like the way the default implementation of
> generations uses file naming conventions like that. If we are going to have
> naming conventions, why not have GS MIGRATION profile naming conventions?
>
> We could still use utilities to register versions and the associated
> migration step. In fact, forget the naming convention:
>
> class IMigration(Interface):
>
>   id = schema.Int("The migration should be id 1, and then subsequent ones
> should be id 2, 3 and so on")
>  
>   to_version = schema.TextLine("Which version is this migration step
> bringing you to?")
>
>   profile = schema.TextLine("The name of an extension profile to run as this
> migration step")
>
> class Migration(object):
>      implements(IMigration)
>      def __init__(self, id, to_version, profile):
>          self.id = self
>          self.to_version = version
>          self.profile = profile
>

Let's compare this to my untested code in
https://svn.plone.org/svn/collective/collective.generations/trunk

  from Products.collective.generations import SchemaManager

  sm = SchemaManager(
      minimum_generation = 0,
      generation = 5,
      package_name = 'Products.eXtremeManagement'
      )

> then, you register a profile, like Products.Poi:migrate-1.0-2.0 and
> Products.Poi:migration-2.0-2.1

That would be something like this:

  <genericsetup:registerProfile
      name="3"
      title="Migration profile for eXtremeManagement generation 2 to 3."
      description="This profile contains configuration changes that
                   are applied during the migration from
                   eXtremeManagement generation 2 to 3, which is part
                   of the change from 1.1 to 1.5."
      directory="migrations/v1.5"
      provides="Products.GenericSetup.interfaces.MIGRATION"
      />

Note that Products.GenericSetup.interfaces.MIGRATION does not
currently exist.  It is just an idea.  But that is not really an issue
here.

> and a few utilities:
>
> v1_0_to_v_2_0 = Migration(1, "2.0", "Products.Poi:migration-1.0-2.0")
> v2_0_to_v_2_1 = Migration(2, "2.1", "Products.Poi:migration-2.0-2.1")
>
><utility component=".migrations.v1_0_to_v_2_0"
> name="Products.Poi.v1_0_to_v_2_0" />
><utility component=".migrations.v2_0_to_v_2_1"
> name="Products.Poi.v2_0_to_v_2_1" />
>
> (we need some thinking about how to separate different products here, maybe
> a property in the utility? can't remember what zope.generation does).

No utilities need to be registered with the collective.generations
approach.  That one SchemaManager should be enough.  Maybe that can be
done in zcml though if wanted.

> Then, all you have to do is to work out the current version, find and order
> the migration utilities for a given product, and execute those profiles
> one-by-one.

In collective.generations I define an UpgradeManager that has this
method which takes a SchemaManager as input and does one step:

    def evolve(manager):
        """Do one evolution step for this manager.
        """
        generation = get_current_generation(manager) + 1
        manager.evolve(self.site, generation)
        set_current_generation(manager, generation)
        transaction.commit()

Also there are methods evolve_minimum and evolve_maximum that evolve
the database to the minimum or the maximum generation as defined by
the SchemaManager.

(I repeat: totally untested.)

> Also, a propertysheet feels quite volatile. It may be nicer to have a local
> utility which keeps track of the current installed version of each
> migration-capable product.

Agreed.  A property sheet feels rather easy for initial testing though.

>> A first install of eXtremeManagement would probably just need to apply
>> the main GS extension profile and set
>> portal_properties.generations.eXtremeManagement to the latest
>> generation number.
>> 
>> I would actually want to shield the user from this migration by simply
>> integrating this in the installer so that it automatically gets called
>> on a reinstall of eXtremeManagement.  I would say for add-on products
>> this makes sense.
>> 
>
> It ought to be an explicit action in Install.py when reinstall=True, but
> that sounds sensible, yes.

Extensions/install.py could have something like this:

  from Products.collective.generations import UpgradeManager
  from Products.collective.generations import SchemaManager

  sm = SchemaManager(
      minimum_generation = 0,
      generation = 5,
      package_name = 'Products.eXtremeManagement'
      )


  def install(context):
      um = UpgradeManager(context) # or getUtility/getToolByName
      um.install(sm)

And during a reinstall it is probably enough to evolve from the
current iteration to the maximum defined generation, using this
method:

      um.evolve_maximum(sm)
      
I do not know if this works, but I *am* beginning to like the
approach. :-)

-- 
Maurits van Rees | http://maurits.vanrees.org/ [NL]
            Work | http://zestsoftware.nl/
"Do not worry about your difficulties in computers,
 I can assure you mine are still greater."


_______________________________________________
Product-Developers mailing list
[email protected]
http://lists.plone.org/mailman/listinfo/product-developers

Reply via email to