#!/usr/bin/env python
# -*-python-*-
#
# Copyright (C) 1999-2006 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
# distribution or at http://viewvc.org/license-1.html.
#
# For more information, visit http://viewvc.org/
#
# -----------------------------------------------------------------------
#
# administrative program for CVSdb; this is primarily
# used to add/rebuild CVS repositories to the database
#
# -----------------------------------------------------------------------
#

#########################################################################
#
# INSTALL-TIME CONFIGURATION
#
# These values will be set during the installation process. During
# development, they will remain None.
#

LIBRARY_DIR = None
CONF_PATHNAME = None

# Adjust sys.path to include our library directory
import sys
import os

if LIBRARY_DIR:
  sys.path.insert(0, LIBRARY_DIR)
else:
  sys.path.insert(0, os.path.abspath(os.path.join(sys.argv[0], "../../lib")))

#########################################################################
  
import os
import string
import cvsdb
import viewvc
import vclib.bincvs


def UpdateFile(db, repository, path, update):
    try:
        if update:
            commit_list = cvsdb.GetUnrecordedCommitList(repository, path, db)
        else:
            commit_list = cvsdb.GetCommitListFromRCSFile(repository, path)
    except cvsdb.error, e:
        print '[ERROR] %s' % (e)
        return

    file = string.join(path, "/")
    if update:
       print '[%s [%d new commits]]' % (file, len(commit_list)),
    else:
       print '[%s [%d commits]]' % (file, len(commit_list)),

    ## add the commits into the database
    for commit in commit_list:
        db.AddCommit(commit)
        sys.stdout.write('.')
        sys.stdout.flush()
    print


def RecurseUpdate(db, repository, directory, update):
    for entry in repository.listdir(directory, None, {}):
        path = directory + [entry.name]

        if entry.errors:
            continue

        if entry.kind is vclib.DIR:
            RecurseUpdate(db, repository, path, update)
            continue

        if entry.kind is vclib.FILE:
            UpdateFile(db, repository, path, update)

def RootPath(path):
    """Break os path into cvs root path and other parts"""
    root = os.path.abspath(path)
    path_parts = []

    p = root
    while 1:
        if os.path.exists(os.path.join(p, 'CVSROOT')):
            root = p
            print "Using repository root `%s'" % root
            break

        p, pdir = os.path.split(p)
        if not pdir:
            del path_parts[:]
            print "Using repository root `%s'" % root
            print "Warning: CVSROOT directory not found."
            break

        path_parts.append(pdir)

    root = cvsdb.CleanRepository(root)
    path_parts.reverse()
    return root, path_parts

def usage():
    print 'Usage: %s <command> [arguments]' % (sys.argv[0])
    print 'Performs administrative functions for the CVSdb database'
    print 'Commands:'
    print '  rebuild <repository>            rebuilds the CVSdb database'
    print '                                  for all files in the repository'
    print '  update <repository>             updates the CVSdb database for'
    print '                                  all unrecorded commits'
    print
    sys.exit(1)


## main
if __name__ == '__main__':
    ## check that a command was given
    if len(sys.argv) <= 2:
        usage()

    ## set the handler function for the command
    command = sys.argv[1]
    if string.lower(command) == 'rebuild':
        update = 0
    elif string.lower(command) == 'update':
        update = 1
    else:
        print 'ERROR: unknown command %s' % (command)
        usage()

    # get repository path
    root, path_parts = RootPath(sys.argv[2])

    ## run command
    try:
      ## connect to the database we are updating
      cfg = viewvc.load_config(CONF_PATHNAME)
      db = cvsdb.ConnectDatabase(cfg)

      repository = vclib.bincvs.BinCVSRepository(None, root, cfg.general)

      RecurseUpdate(db, repository, path_parts, update)

    except KeyboardInterrupt:
        print
        print '** break **'
        
    sys.exit(0)
