#
# Copyright (C) 2015 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function
import os
import shutil
import sys

import git_command
from subcmds import init


GITC_MANIFEST_DIR = '/usr/local/google/gitc'
GITC_FS_ROOT_DIR = '/gitc/sha/rw'
NUM_BATCH_RETRIEVE_REVISIONID = 300


class GitcInit(init.Init):
  common = True
  helpSummary = "Initialize a GITC Client."
  helpUsage = """
%prog [options] [client name]
"""
  helpDescription = """
The '%prog' command is ran to initialize a new GITC client for use
with the GITC file system.

This command will setup the client directory, initialize repo, just
like repo init does, and then downloads the manifest collection
and installs in in the .repo/directory of the GITC client.

Once this is done, a GITC manifest is generated by pulling the HEAD
SHA for each project and generates the properly formatted XML file
and installs it as .manifest in the GITC client directory.

The -c argument is required to specify the GITC client name.

The optional -f argument can be used to specify the manifest file to
use for this GITC client.
"""

  def _Options(self, p):
    super(GitcInit, self)._Options(p)
    g = p.add_option_group('GITC options')
    g.add_option('-f', '--manifest-file',
                 dest='manifest_file',
                 help='Optional manifest file to use for this GITC client.')
    g.add_option('-c', '--gitc-client',
                 dest='gitc_client',
                 help='The name for the new gitc_client instance.')

  def Execute(self, opt, args):
    if not opt.gitc_client:
      print('fatal: gitc client (-c) is required', file=sys.stderr)
      sys.exit(1)
    self.client_dir = os.path.join(GITC_MANIFEST_DIR, opt.gitc_client)
    if not os.path.exists(GITC_MANIFEST_DIR):
      os.makedirs(GITC_MANIFEST_DIR)
    if not os.path.exists(self.client_dir):
      os.mkdir(self.client_dir)
    super(GitcInit, self).Execute(opt, args)
    if opt.manifest_file:
      if not os.path.exists(opt.manifest_file):
        print('fatal: Specified manifest file %s does not exist.' %
              opt.manifest_file)
        sys.exit(1)
      shutil.copyfile(opt.manifest_file,
                      os.path.join(self.client_dir, '.manifest'))
    else:
      self._GenerateGITCManifest()
    print('Please run `cd %s` to view your GITC client.' %
          os.path.join(GITC_FS_ROOT_DIR, opt.gitc_client))

  def _SetProjectRevisions(self, projects, branch):
    """Sets the revisionExpr for a list of projects.

    Because of the limit of open file descriptors allowed, length of projects
    should not be overly large. Recommend calling this function multiple times
    with each call not exceeding NUM_BATCH_RETRIEVE_REVISIONID projects.

    @param projects: List of project objects to set the revionExpr for.
    @param branch: The remote branch to retrieve the SHA from. If branch is
                   None, 'HEAD' is used.
    """
    project_gitcmds = [(
        project, git_command.GitCommand(None,
                                        ['ls-remote',
                                         project.remote.url,
                                         branch], capture_stdout=True))
        for project in projects]
    for proj, gitcmd in project_gitcmds:
      if gitcmd.Wait():
        print('FATAL: Failed to retrieve revisionID for %s' % project)
        sys.exit(1)
      proj.revisionExpr = gitcmd.stdout.split('\t')[0]

  def _GenerateGITCManifest(self):
    """Generate a manifest for shafsd to use for this GITC client."""
    print('Generating GITC Manifest by fetching revision SHAs for each '
          'project.')
    manifest = self.manifest
    project_gitcmd_dict = {}
    index = 0
    while index < len(manifest.projects):
      self._SetProjectRevisions(
          manifest.projects[index:(index+NUM_BATCH_RETRIEVE_REVISIONID)],
          manifest.default.revisionExpr)
      index += NUM_BATCH_RETRIEVE_REVISIONID
    # Save the manifest.
    with open(os.path.join(self.client_dir, '.manifest'), 'w') as f:
      manifest.Save(f)
