Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / common / extensions / docs / server2 / app_yaml_helper.py
blobd2bb706f97a7d133209336a17b48ef574b97f225
1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 import logging
7 from extensions_paths import APP_YAML
10 _APP_YAML_CONTAINER = '''
11 application: chrome-apps-doc
12 version: %s
13 runtime: python27
14 api_version: 1
15 threadsafe: false
16 '''
19 class AppYamlHelper(object):
20 '''Parses the app.yaml file, and is able to step back in the host file
21 system's revision history to find when it changed to some given version.
22 '''
23 def __init__(self,
24 object_store_creator,
25 host_file_system_provider):
26 self._store = object_store_creator.Create(
27 AppYamlHelper,
28 category=host_file_system_provider.GetTrunk().GetIdentity(),
29 start_empty=False)
30 self._host_file_system_provider = host_file_system_provider
32 @staticmethod
33 def ExtractVersion(app_yaml, key='version'):
34 '''Extracts the 'version' key from the contents of an app.yaml file.
35 Allow overriding the key to parse e.g. the cron file ('target').
36 '''
37 # We could properly parse this using a yaml library but Python doesn't have
38 # one built in so whatevs.
39 key_colon = '%s:' % key
40 versions = [line.strip()[len(key_colon):].strip()
41 for line in app_yaml.split('\n')
42 if line.strip().startswith(key_colon)]
43 if not versions:
44 raise ValueError('No versions found for %s in %s' % (
45 key, app_yaml))
46 if len(set(versions)) > 1:
47 raise ValueError('Inconsistent versions found for %s in %s: %s' % (
48 key, app_yaml, versions))
49 return versions[0]
51 @staticmethod
52 def IsGreater(lhs, rhs):
53 '''Return whether the app.yaml version |lhs| > |rhs|. This is tricky
54 because versions are typically not numbers but rather 2-0-9, 2-0-12,
55 2-1-0, etc - and 2-1-0 > 2-0-10 > 2-0-9.
56 '''
57 lhs_parts = lhs.replace('-', '.').split('.')
58 rhs_parts = rhs.replace('-', '.').split('.')
59 while lhs_parts and rhs_parts:
60 lhs_msb = int(lhs_parts.pop(0))
61 rhs_msb = int(rhs_parts.pop(0))
62 if lhs_msb != rhs_msb:
63 return lhs_msb > rhs_msb
64 return len(lhs) > len(rhs)
66 @staticmethod
67 def GenerateAppYaml(version):
68 '''Probably only useful for tests.
69 '''
70 return _APP_YAML_CONTAINER % version
72 def IsUpToDate(self, app_version):
73 '''Returns True if the |app_version| is up to date with respect to the one
74 checked into the host file system.
75 '''
76 checked_in_app_version = AppYamlHelper.ExtractVersion(
77 self._host_file_system_provider.GetTrunk().ReadSingle(APP_YAML).Get())
78 if app_version == checked_in_app_version:
79 return True
80 if AppYamlHelper.IsGreater(app_version, checked_in_app_version):
81 logging.warning(
82 'Server is too new! Checked in %s < currently running %s' % (
83 checked_in_app_version, app_version))
84 return True
85 return False
87 def GetFirstRevisionGreaterThan(self, app_version):
88 '''Finds the first revision that the version in app.yaml was greater than
89 |app_version|.
91 WARNING: if there is no such revision (e.g. the app is up to date, or
92 *oops* the app is even newer) then this will throw a ValueError. Use
93 IsUpToDate to validate the input before calling this method.
94 '''
95 stored = self._store.Get(app_version).Get()
96 if stored is None:
97 stored = self._GetFirstRevisionGreaterThanImpl(app_version)
98 assert stored is not None
99 self._store.Set(app_version, stored)
100 return stored
102 def _GetFirstRevisionGreaterThanImpl(self, app_version):
103 def get_app_yaml_revision(file_system):
104 return int(file_system.Stat(APP_YAML).version)
106 def has_greater_app_version(file_system):
107 app_version_in_file_system = AppYamlHelper.ExtractVersion(
108 file_system.ReadSingle(APP_YAML).Get())
109 return AppYamlHelper.IsGreater(app_version_in_file_system, app_version)
111 found = None
112 next_file_system = self._host_file_system_provider.GetTrunk()
114 while has_greater_app_version(next_file_system):
115 found = get_app_yaml_revision(next_file_system)
116 # Back up a revision then find when app.yaml was last updated before then.
117 if found == 0:
118 logging.warning('All revisions are greater than %s' % app_version)
119 return 0
120 next_file_system = self._host_file_system_provider.GetTrunk(
121 revision=found - 1)
123 if found is None:
124 raise ValueError('All revisions are less than %s' % app_version)
125 return found