# 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 reno import loader
from reno import scanner
from reno import utils

import yaml

import sys


def build_cache_db(reporoot, notesdir, branch, collapse_pre_releases,
                   versions_to_include, earliest_version):
    notes = scanner.get_notes_by_version(
        reporoot, notesdir, branch,
        collapse_pre_releases=collapse_pre_releases,
        earliest_version=earliest_version,
    )

    # Default to including all versions returned by the scanner.
    if not versions_to_include:
        versions_to_include = list(notes.keys())

    # Build a cache data structure including the file contents as well
    # as the basic data returned by the scanner.
    file_contents = {}
    for version in versions_to_include:
        for filename, sha in notes[version]:
            body = scanner.get_file_at_commit(
                reporoot,
                filename,
                sha,
            )
            # We want to save the contents of the file, which is YAML,
            # inside another YAML file. That looks terribly ugly with
            # all of the escapes needed to format it properly as
            # embedded YAML, so parse the input and convert it to a
            # data structure that can be serialized cleanly.
            y = yaml.safe_load(body)
            file_contents[filename] = y

    cache = {
        'notes': [
            {'version': k, 'files': v}
            for k, v in notes.items()
        ],
        'file-contents': file_contents,
    }
    return cache


def cache_cmd(args):
    "Generates a release notes cache"
    reporoot = args.reporoot.rstrip('/') + '/'
    notesdir = utils.get_notes_dir(args)
    if args.output == '-':
        stream = sys.stdout
        close_stream = False
    elif args.output:
        stream = open(args.output, 'w')
        close_stream = True
    else:
        stream = open(loader.get_cache_filename(reporoot, notesdir), 'w')
        close_stream = True
    try:
        cache = build_cache_db(
            reporoot=reporoot,
            notesdir=notesdir,
            branch=args.branch,
            collapse_pre_releases=args.collapse_pre_releases,
            versions_to_include=args.version,
            earliest_version=args.earliest_version,
        )
        yaml.safe_dump(
            cache,
            stream,
            allow_unicode=True,
            explicit_start=True,
            encoding='utf-8',
        )
    finally:
        if close_stream:
            stream.close()
    return

@@ -539,16 +539,38 @@
 cense.%0A%0A
+import os%0Aimport sys%0A%0A
 from ren
@@ -647,28 +647,16 @@
 t yaml%0A%0A
-import sys%0A%0A
 %0Adef bui
@@ -2074,169 +2074,657 @@
 def 
-cache_cmd(args):%0A    %22Generates a release notes cache%22%0A    reporoot = args.reporoot.rstrip('/') + '/'%0A    notesdir = 
+write_cache_db(reporoot, notesdir, branch, collapse_pre_releases,%0A                   versions_to_include, earliest_version,%0A                   outfilename=None):%0A    %22%22%22Create a cache database file for the release notes data.%0A%0A    Build the cache database from scanning the project history and%0A    write it to a file within the project.%0A%0A    By default, the data is written to the same file the scanner will%0A    try to read when it cannot look at the git history. If o
 ut
+f
 il
-s.get_notes_dir(args)%0A    if args.output
+ename%0A    is given and is '-' the data is written to stdout%0A    instead. Otherwise, if outfilename is given, the data overwrites%0A    the named file.%0A%0A    %22%22%22%0A    if outfilename
  == 
@@ -2794,27 +2794,27 @@
    elif 
-args.output
+outfilename
 :%0A      
@@ -2833,19 +2833,19 @@
 pen(
-args.output
+outfilename
 , 'w
@@ -2893,30 +2893,30 @@
         
-stre
+outfilen
 am
+e
  = 
-open(
 loader.g
@@ -2952,16 +2952,165 @@
 otesdir)
+%0A        if not os.path.exists(os.path.dirname(outfilename)):%0A            os.makedirs(os.path.dirname(outfilename))%0A        stream = open(outfilename
 , 'w')%0A 
@@ -3258,21 +3258,16 @@
  branch=
-args.
 branch,%0A
@@ -3300,21 +3300,16 @@
 eleases=
-args.
 collapse
@@ -3359,20 +3359,27 @@
 ude=
-args.
 version
+s_to_include
 ,%0A  
@@ -3409,13 +3409,8 @@
 ion=
-args.
 earl
@@ -3666,16 +3666,454 @@
 close()%0A
+%0A%0Adef cache_cmd(args):%0A    %22Generates a release notes cache%22%0A    reporoot = args.reporoot.rstrip('/') + '/'%0A    notesdir = utils.get_notes_dir(args)%0A    write_cache_db(%0A        reporoot=reporoot,%0A        notesdir=notesdir,%0A        branch=args.branch,%0A        collapse_pre_releases=args.collapse_pre_releases,%0A        versions_to_include=args.version,%0A        earliest_version=args.earliest_version,%0A        outfilename=args.output,%0A    )%0A
     retu

add API for writing the cache file