# (C) 2005 Canonical

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

"""Plugin to force-reweave the inventory of a branch.

This makes sure that the inventory weave's DAG of ancestry is correct so that
attempts to fetch the branch over http, or certain merge operations cope
correctly.

This is most likely needed if you have used fetch-ghosts from bzrlib to
resolve ghosts after a baz (or otherwise) import and you get bizarre behaviour
when either exporting over http or when merging from other translated branches.
"""

from bzrlib.commands import Command
from bzrlib.weavefile import write_weave_v5 as w5

import bzrlib.branch
import bzrlib.progress

import os

class cmd_fix(Command):
    """Force-reweave the inventory in this branch.

    The branch URL *MUST* be on the local filesystem."""
    takes_args = ['branch_dir?']

    def run(self, branch_dir="."):
        branch = bzrlib.branch.Branch.open(branch_dir)
        branch.lock_write()
        try:
            self._do_reweave(branch, branch_dir)
        finally:
            branch.unlock()

    @staticmethod
    def _do_reweave(branch, branch_dir):
        inventory_weave = branch._get_inventory_weave()

        new_weave = bzrlib.weave.Weave()

        pending = list(inventory_weave.iter_names())
        total = len(pending)
        progress = bzrlib.progress.ProgressBar()

        while pending:
            index = pending.pop(0)
            done = total - len(pending)
            progress.update('re-weaving', done, total)
            rev = branch.get_revision(index)
            parents = []
            for parent in rev.parent_ids:
                if parent in inventory_weave:
                    parents.append(parent)
            unavailable = [p for p in parents if p not in new_weave]
            if len(unavailable) == 0:
                new_weave.add(index, parents, inventory_weave.get(index))
            else:
                pending.append(index)

                
        progress.update('Writing weave')

        out_file_name = os.path.join(branch_dir, ".bzr", "inventory.weave")
        f = open(out_file_name+".tmp", "w")
        w5(new_weave, f)
        f.close()
        os.rename(out_file_name+".tmp", out_file_name)

        progress.clear()
