
#include "cmt_std.h"
#include "cmt_system.h"

//----------------------------------------------------------
class FileScanner
{
public:
  class actor
  {
  public:
    virtual void run ()
    {
    }
  };

  FileScanner (const cmt_string& new_root);
  bool scan (actor& a);

private:
  void scan (int level, actor& a);

  cmt_string m_root;
  cmt_string m_full_root;
};
//----------------------------------------------------------

//----------------------------------------------------------
FileScanner::FileScanner (const cmt_string& new_root) : 
  m_root(new_root),
  m_full_root(new_root)
//----------------------------------------------------------
{
  if (m_root[0] == ':')
    {
      //
      // The new CVS root points to a remote repository.
      //
      int pos = m_root.find_last_of (":");
      if (pos != cmt_string::npos)
	{
	  m_root.erase (0, pos);
	}
      else
	{
	  // A syntax error ???
	  cout << "The new CVS root is wrongly specified :[" << m_full_root << "]" << endl;
	}
    }
}

//----------------------------------------------------------
bool FileScanner::scan (actor& a)
//----------------------------------------------------------
{
  scan (0, a);

  return (true);
}

//----------------------------------------------------------
void FileScanner::scan (int level, actor& a)
//----------------------------------------------------------
{
  CmtSystem::cmt_string_vector list;

  CmtSystem::scan_dir ("*", list);

  if (list.size () == 0) return;

  // Will be set if at least one sub-directory is a CVS directory
  bool has_cvs = false;

  if (CmtSystem::test_directory ("CVS")) has_cvs = true;

  if (!has_cvs) return;

  cmt_string cvs_root;
  cmt_string cvs_repository;

  cvs_root.read ("CVS/Root");
  cvs_repository.read ("CVS/Repository");

  int pos;

  if (cvs_root[0] == ':')
    {
      //
      // The current CVS root points to a remote repository.
      //
      pos = cvs_root.find_last_of (":");
      if (pos != cmt_string::npos)
	{
	  cvs_root.erase (0, pos);
	}
      else
	{
	  // A syntax error ???
	  cout << "The CVS/Root file is corrupted" << endl;
	  return;
	}
    }

  pos = cvs_repository.find (cvs_root);
  if (pos == 0)
    {
      cvs_repository.replace (cvs_root, m_root);
    }
  else
    {
      // This case should never happen !!!
      cout << "The CVS/Repository file does not match CVS/Root" << endl;
      return;
    }
  
  if (m_full_root.write ("CVS/Root"))
    {
      cout << "CVS root changed from " << cvs_root << " to " << m_full_root << endl;
    }
  else
    {
      cout << "cannot change CVS root in " << CmtSystem::pwd () << endl;
    }

  if (cvs_repository.write ("CVS/Repository"))
    {
      cout << "CVS repository changed from " << cvs_root << " to " << m_root << endl;
    }
  else
    {
      cout << "cannot change CVS repository in " << CmtSystem::pwd () << endl;
    }

  int i;
  for (i = 0; i < list.size (); i++)
    {
      cmt_string& name = list[i];

      if (name[0] == CmtSystem::file_separator ()) name.erase (0, 1);

      if (CmtSystem::test_directory (name))
	{
	  CmtSystem::cd (name);
	  scan (level + 1, a);
	  CmtSystem::cd ("..");
	}
    }
}

int main (int argc, char* argv[])
{
  if (argc < 2)
    {
      printf ("cvsmove <new-repository>\n");
      return (1);
    }

  cmt_string new_repository = argv[1];

  FileScanner scanner (new_repository);
  FileScanner::actor actor;
	
  CmtSystem::cd ("..");
  scanner.scan (actor);

  return (0);
}
