Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(579)

Side by Side Diff: chrome/common/extensions/docs/server2/path_canonicalizer.py

Issue 15087006: Docserver: there is only one. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: epic rebase Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright 2013 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import logging
5 import os 6 import os
7 import posixpath
8 import traceback
9
10 from branch_utility import BranchUtility
11 from file_system import FileNotFoundError
6 from third_party.json_schema_compiler.model import UnixName 12 from third_party.json_schema_compiler.model import UnixName
7 import svn_constants 13 import svn_constants
8 14
15 def _SimplifyFileName(file_name):
16 return (posixpath.splitext(file_name)[0]
17 .lower()
18 .replace('.', '')
19 .replace('-', '')
20 .replace('_', ''))
21
9 class PathCanonicalizer(object): 22 class PathCanonicalizer(object):
10 '''Transforms paths into their canonical forms. Since the dev server has had 23 '''Transforms paths into their canonical forms. Since the dev server has had
11 many incarnations - e.g. there didn't use to be apps/ - there may be old 24 many incarnations - e.g. there didn't use to be apps/ - there may be old
12 paths lying around the webs. We try to redirect those to where they are now. 25 paths lying around the webs. We try to redirect those to where they are now.
13 ''' 26 '''
14 def __init__(self, channel, compiled_fs_factory): 27 def __init__(self, compiled_fs_factory):
15 self._channel = channel 28 # Map of simplified API names (for typo detection) to their real paths.
16 self._identity_fs = compiled_fs_factory.CreateIdentity(PathCanonicalizer) 29 def make_public_apis(_, file_names):
30 return dict((_SimplifyFileName(name), name) for name in file_names)
31 self._public_apis = compiled_fs_factory.Create(make_public_apis,
32 PathCanonicalizer)
17 33
18 def Canonicalize(self, path): 34 def Canonicalize(self, path):
19 starts_with_channel, path_without_channel = (False, path) 35 '''Returns the canonical path for |path|, and whether that path is a
20 if path.startswith('%s/' % self._channel): 36 permanent canonicalisation (e.g. when we redirect from a channel to a
21 starts_with_channel, path_without_channel = ( 37 channel-less URL) or temporary (e.g. when we redirect from an apps-only API
22 True, path[len(self._channel) + 1:]) 38 to an extensions one - we may at some point enable it for extensions).
39 '''
40 class ReturnType(object):
41 def __init__(self, path, permanent):
42 self.path = path
43 self.permanent = permanent
23 44
24 if any(path.startswith(prefix) 45 # Catch incorrect comparisons by disabling ==/!=.
25 for prefix in ('extensions/', 'apps/', 'static/')): 46 def __eq__(self, _): raise NotImplementedError()
26 return path 47 def __ne__(self, _): raise NotImplementedError()
27 48
28 if '/' in path_without_channel or path_without_channel == '404.html': 49 # Strip any channel info off it. There are no channels anymore.
29 return path 50 for channel_name in BranchUtility.GetAllChannelNames():
51 channel_prefix = channel_name + '/'
52 if path.startswith(channel_prefix):
53 # Redirect now so that we can set the permanent-redirect bit. Channel
54 # redirects are the only things that should be permanent redirects;
55 # anything else *could* change, so is temporary.
56 return ReturnType(path[len(channel_prefix):], True)
30 57
31 apps_templates = self._identity_fs.GetFromFileListing( 58 # No further work needed for static.
32 '/'.join((svn_constants.PUBLIC_TEMPLATE_PATH, 'apps'))) 59 if path.startswith('static/'):
33 extensions_templates = self._identity_fs.GetFromFileListing( 60 return ReturnType(path, False)
34 '/'.join((svn_constants.PUBLIC_TEMPLATE_PATH, 'extensions')))
35 61
36 if self._channel is None or not starts_with_channel: 62 # People go to just "extensions" or "apps". Redirect to the directory.
37 apps_path = 'apps/%s' % path_without_channel 63 if path in ('extensions', 'apps'):
38 extensions_path = 'extensions/%s' % path_without_channel 64 return ReturnType(path + '/', False)
65
66 # The rest of this function deals with trying to figure out what API page
67 # for extensions/apps to redirect to, if any. We see a few different cases
68 # here:
69 # - Unqualified names ("browserAction.html"). These are easy to resolve;
70 # figure out whether it's an extension or app API and redirect.
71 # - but what if it's both? Well, assume extensions. Maybe later we can
72 # check analytics and see which is more popular.
73 # - Wrong names ("apps/browserAction.html"). This really does happen,
74 # damn it, so do the above logic but record which is the default.
75 if path.startswith(('extensions/', 'apps/')):
76 default_platform, reference_path = path.split('/', 1)
39 else: 77 else:
40 apps_path = '%s/apps/%s' % (self._channel, path_without_channel) 78 default_platform, reference_path = ('extensions', path)
41 extensions_path = '%s/extensions/%s' % (self._channel,
42 path_without_channel)
43 79
44 unix_path = UnixName(os.path.splitext(path_without_channel)[0]) 80 try:
45 if unix_path in extensions_templates: 81 apps_public = self._public_apis.GetFromFileListing(
46 return extensions_path 82 '/'.join((svn_constants.PUBLIC_TEMPLATE_PATH, 'apps')))
47 if unix_path in apps_templates: 83 extensions_public = self._public_apis.GetFromFileListing(
48 return apps_path 84 '/'.join((svn_constants.PUBLIC_TEMPLATE_PATH, 'extensions')))
49 return extensions_path 85 except FileNotFoundError:
86 # Probably offline.
87 logging.warning(traceback.format_exc())
88 return ReturnType(path, False)
89
90 simple_reference_path = _SimplifyFileName(reference_path)
91 apps_path = apps_public.get(simple_reference_path)
92 extensions_path = extensions_public.get(simple_reference_path)
93
94 if apps_path is None:
95 if extensions_path is None:
96 # No idea. Just return the original path. It'll probably 404.
97 pass
98 else:
99 path = 'extensions/%s' % extensions_path
100 else:
101 if extensions_path is None:
102 path = 'apps/%s' % apps_path
103 else:
104 assert apps_path == extensions_path
105 path = '%s/%s' % (default_platform, apps_path)
106
107 return ReturnType(path, False)
OLDNEW
« no previous file with comments | « chrome/common/extensions/docs/server2/patcher.py ('k') | chrome/common/extensions/docs/server2/path_canonicalizer_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698