docs: def promote(self, cart_name):
          """
          `name` - name of cart
  
          Promote a cart from its current environment to the next in the chain.
          """
          cart = juicer.common.Cart.Cart(cart_name=cart_name, autoload=True, autosync=True)
          old_env = cart.current_env
          cart.current_env = juicer.utils.get_next_environment(cart.current_env)
  
          # figure out what needs to be done to promote packages. If
          # packages are going between environments that are on the same
          # host and we don't need to sign them just associate with both
          # repos.
          if juicer.utils.env_same_host(old_env, cart.current_env) and (self.connectors[old_env].requires_signature == self.connectors[cart.current_env].requires_signature):
              juicer.utils.Log.log_info("Envs %s and %s exist on the same host, calling remote associate action" % (old_env, cart.current_env))
              juicer.utils.Log.log_info("Promoting %s from %s to %s" %
                      (cart_name, old_env, cart.current_env))
              # iterate through packages and associate to new repo
              for repo, items in cart.iterrepos():
                  query = '/repositories/%s-%s/actions/associate/' % (repo, cart.current_env)
                  for item in items:
                      source_repo_id = '%s-%s' % (repo, old_env)
                      data = {
                          'source_repo_id': str(source_repo_id),
                          'criteria': {
                              'type_ids': ['rpm'],
                              'filters': {
                                  'unit': {
                                      'filename': str(item.path.split('/')[-1])
                                      }
                                  }
                              }
                          }
                      _r = self.connectors[cart.current_env].post(query, data)
                      if _r.status_code != Constants.PULP_POST_ACCEPTED:
                          raise JuicerPulpError("Package association call was not accepted. Terminating!")
                      else:
                          # association was accepted so publish destination repo
                          con = self.connectors[cart.current_env]
                          con.post('/repositories/%s-%s/actions/publish/' % (repo, cart.current_env), {'id': 'yum_distributor'})
                          # also update the item's remote path
                          filename = item.path.split('/')[-1]
                          item.update('%s/%s' % (juicer.utils.pulp_repo_path(con, '%s-%s' % (repo, cart.current_env)), filename))
              # we didn't bomb out yet so let the user know what's up
              juicer.utils.Log.log_info("Package association calls were accepted. Trusting that your packages existed in %s" % old_env)
              # we can save and publish here because upload does this too...
              cart.save()
              self.publish(cart)
          else:
              juicer.utils.Log.log_debug("Syncing down rpms...")
              cart.sync_remotes()
              self.sign_cart_for_env_maybe(cart, cart.current_env)
  
              juicer.utils.Log.log_info("Promoting %s from %s to %s" %
                      (cart_name, old_env, cart.current_env))
  
              for repo in cart.repos():
                  juicer.utils.Log.log_debug("Promoting %s to %s in %s" %
                                             (cart[repo], repo, cart.current_env))
              # reiterating that upload will save and publish the cart
              self.upload(cart.current_env, cart)