1# Copyright (c) 2012 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.
4
5"""Presubmit script to verify that XIB changes are done with the right version.
6
7See http://dev.chromium.org/developers/design-documents/mac-xib-files for more
8information.
9"""
10
11import re
12
13# Minimum is Mac OS X 10.8.1 (12B19).
14HUMAN_DARWIN_VERSION = '10.8.x, x >= 1'
15ALLOWED_DARWIN_VERSION = 12  # Darwin 12 = 10.8.
16MINIMUM_DARWIN_RELEASE = 'B'  # Release B = 10.8.1.
17
18MINIMUM_IB_VERSION = 2549  # Xcode 4.4.1.
19MAXIMUM_IB_VERSION = 3084  # Xcode 4.6.x.
20HUMAN_IB_VERSION = '>= 4.4.1, <= 4.6.x'
21
22SYSTEM_VERSION_RE = r'<string key="IBDocument\.SystemVersion">' + \
23    '([0-9]{,2})([A-Z])([0-9]+)</string>'
24
25IB_VERSION_RE = \
26    r'<string key="IBDocument\.InterfaceBuilderVersion">([0-9]+)</string>'
27
28def _CheckXIBSystemAndXcodeVersions(input_api, output_api, error_type):
29  affected_xibs = [x for x in input_api.AffectedFiles()
30      if x.LocalPath().endswith('.xib')]
31
32  incorrect_system_versions = []
33  incorrect_ib_versions = []
34
35  for xib in affected_xibs:
36    if len(xib.NewContents()) == 0:
37      continue
38
39    system_version = None
40    ib_version = None
41
42    new_contents = xib.NewContents()
43    if not new_contents:
44      # Deleting files is always fine.
45      continue
46
47    for line in new_contents:
48      m = re.search(SYSTEM_VERSION_RE, line)
49      if m:
50        system_version = (m.group(1), m.group(2), m.group(3))
51
52      m = re.search(IB_VERSION_RE, line)
53      if m:
54        ib_version = m.group(1)
55
56      if system_version is not None and ib_version is not None:
57        break
58
59    if system_version is None:
60      incorrect_system_versions.append(xib.LocalPath())
61      continue
62    if int(system_version[0]) != ALLOWED_DARWIN_VERSION:
63      incorrect_system_versions.append(xib.LocalPath())
64      continue
65    if system_version[1] < MINIMUM_DARWIN_RELEASE:
66      incorrect_system_versions.append(xib.LocalPath())
67      continue
68
69    if ib_version is None or int(ib_version) < MINIMUM_IB_VERSION or \
70       int(ib_version) > MAXIMUM_IB_VERSION:
71      incorrect_ib_versions.append(xib.LocalPath())
72      continue
73
74  problems = []
75  if incorrect_system_versions:
76    problems.append(error_type(
77        'XIB files need to be saved on Mac OS X ' + HUMAN_DARWIN_VERSION,
78        items=incorrect_system_versions))
79  if incorrect_ib_versions:
80    problems.append(error_type(
81        'XIB files need to be saved using Xcode version ' + HUMAN_IB_VERSION,
82        items=incorrect_ib_versions))
83  return problems
84
85def CheckChangeOnUpload(input_api, output_api):
86  # Allow uploads to happen even if the presubmit fails, so that contributors
87  # can ask their reviewer or another person to re-save the XIBs for them.
88  return _CheckXIBSystemAndXcodeVersions(input_api, output_api,
89      error_type=output_api.PresubmitPromptWarning)
90
91def CheckChangeOnCommit(input_api, output_api):
92  return _CheckXIBSystemAndXcodeVersions(input_api, output_api,
93      error_type=output_api.PresubmitError)
94