• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3#
4# Copyright © 2018 Thibault Saunier <tsaunier@igalia.com>
5#
6# This library is free software; you can redistribute it and/or modify it under
7# the terms of the GNU Lesser General Public License as published by the Free
8# Software Foundation; either version 2.1 of the License, or (at your option)
9# any later version.
10#
11# This library is distributed in the hope that it will be useful, but WITHOUT
12# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
14# details.
15#
16# You should have received a copy of the GNU Lesser General Public License
17# along with this library.  If not, see <http://www.gnu.org/licenses/>.
18
19import argparse
20import json
21import os
22import sys
23import re
24import subprocess
25import tempfile
26
27from collections import OrderedDict
28try:
29    from collections.abc import Mapping
30except ImportError:  # python <3.3
31    from collections import Mapping
32
33
34# Marks values in the json file as "unstable" so that they are
35# not updated automatically, this aims at making the cache file
36# stable and handle corner cases were we can't automatically
37# make it happen. For properties, the best way is to use th
38# GST_PARAM_DOC_SHOW_DEFAULT flag.
39UNSTABLE_VALUE = "unstable-values"
40
41
42
43def dict_recursive_update(d, u):
44    modified = False
45    unstable_values = d.get(UNSTABLE_VALUE, [])
46    if not isinstance(unstable_values, list):
47        unstable_values = [unstable_values]
48    for k, v in u.items():
49        if isinstance(v, Mapping):
50            r = d.get(k, {})
51            modified |= dict_recursive_update(r, v)
52            d[k] = r
53        elif k not in unstable_values:
54            modified = True
55            if k == "package":
56                d[k] = re.sub(" git$| source release$| prerelease$", "", v)
57            else:
58                d[k] = u[k]
59    return modified
60
61
62def test_unstable_values():
63    current_cache = { "v1": "yes", "unstable-values": "v1"}
64    new_cache = { "v1": "no" }
65
66    assert(dict_recursive_update(current_cache, new_cache) == False)
67
68    new_cache = { "v1": "no", "unstable-values": "v2" }
69    assert(dict_recursive_update(current_cache, new_cache) == True)
70
71    current_cache = { "v1": "yes", "v2": "yay", "unstable-values": "v1",}
72    new_cache = { "v1": "no" }
73    assert(dict_recursive_update(current_cache, new_cache) == False)
74
75    current_cache = { "v1": "yes", "v2": "yay", "unstable-values": "v2"}
76    new_cache = { "v1": "no", "v2": "unstable" }
77    assert (dict_recursive_update(current_cache, new_cache) == True)
78    assert (current_cache == { "v1": "no", "v2": "yay", "unstable-values": "v2" })
79
80if __name__ == "__main__":
81    cache_filename = sys.argv[1]
82    output_filename = sys.argv[2]
83    build_root = os.environ.get('MESON_BUILD_ROOT', '')
84
85    subenv = os.environ.copy()
86    cache = {}
87    try:
88        with open(cache_filename, newline='\n', encoding='utf8') as f:
89            cache = json.load(f)
90    except FileNotFoundError:
91        pass
92
93    out = output_filename + '.tmp'
94    cmd = [os.path.join(os.path.dirname(os.path.realpath(__file__)), 'gst-hotdoc-plugins-scanner'), out]
95    gst_plugins_paths = []
96    for plugin_path in sys.argv[3:]:
97        cmd.append(plugin_path)
98        gst_plugins_paths.append(os.path.dirname(plugin_path))
99
100    try:
101        with open(os.path.join(build_root, 'GstPluginsPath.json'), newline='\n', encoding='utf8') as f:
102            plugin_paths = os.pathsep.join(json.load(f))
103    except FileNotFoundError:
104        plugin_paths = ""
105
106    if plugin_paths:
107        subenv['GST_PLUGIN_PATH'] = subenv.get('GST_PLUGIN_PATH', '') + ':' + plugin_paths
108
109    # Hide stderr unless an actual error happens as we have cases where we get g_warnings
110    # and other issues because plugins are being built while `gst_init` is called
111    stderrlogfile = output_filename + '.stderr'
112    with open(stderrlogfile, 'w', encoding='utf8') as log:
113        try:
114            data = subprocess.check_output(cmd, env=subenv, stderr=log, encoding='utf8', universal_newlines=True)
115        except subprocess.CalledProcessError as e:
116            log.flush()
117            with open(stderrlogfile, 'r', encoding='utf8') as f:
118                print(f.read(), file=sys.stderr)
119            raise
120
121    with open(out, 'r', newline='\n', encoding='utf8') as jfile:
122        try:
123            plugins = json.load(jfile, object_pairs_hook=OrderedDict)
124        except json.decoder.JSONDecodeError:
125            print("Could not decode:\n%s" % jfile.read(), file=sys.stderr)
126            raise
127
128    modified = dict_recursive_update(cache, plugins)
129
130    with open(output_filename, 'w', newline='\n', encoding='utf8') as f:
131        json.dump(cache, f, indent=4, sort_keys=True, ensure_ascii=False)
132
133    if modified:
134        with open(cache_filename, 'w', newline='\n', encoding='utf8') as f:
135            json.dump(cache, f, indent=4, sort_keys=True, ensure_ascii=False)
136