branch_utility.py revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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 5import json 6import logging 7 8import object_store 9import operator 10 11class BranchUtility(object): 12 def __init__(self, base_path, fetcher, object_store): 13 self._base_path = base_path 14 self._fetcher = fetcher 15 self._object_store = object_store 16 17 @staticmethod 18 def GetAllBranchNames(): 19 return ['stable', 'beta', 'dev', 'trunk'] 20 21 def GetAllBranchNumbers(self): 22 return [(branch, self.GetBranchNumberForChannelName(branch)) 23 for branch in BranchUtility.GetAllBranchNames()] 24 25 def SplitChannelNameFromPath(self, path): 26 """Splits the channel name out of |path|, returning the tuple 27 (channel_name, real_path). If the channel cannot be determined then returns 28 (None, path). 29 """ 30 if '/' in path: 31 first, second = path.split('/', 1) 32 else: 33 first, second = (path, '') 34 if first in ['trunk', 'dev', 'beta', 'stable']: 35 return (first, second) 36 return (None, path) 37 38 def GetBranchNumberForChannelName(self, channel_name): 39 """Returns the branch number for a channel name. 40 """ 41 if channel_name == 'trunk': 42 return 'trunk' 43 44 branch_number = self._object_store.Get(channel_name + '.' + self._base_path, 45 object_store.BRANCH_UTILITY).Get() 46 if branch_number is not None: 47 return branch_number 48 49 try: 50 version_json = json.loads(self._fetcher.Fetch(self._base_path).content) 51 except Exception as e: 52 # This can happen if omahaproxy is misbehaving, which we've seen before. 53 # Quick hack fix: just serve from trunk until it's fixed. 54 logging.error('Failed to fetch or parse branch from omahaproxy: %s! ' 55 'Falling back to "trunk".' % e) 56 return 'trunk' 57 58 branch_numbers = {} 59 for entry in version_json: 60 if entry['os'] not in ['win', 'linux', 'mac', 'cros']: 61 continue 62 for version in entry['versions']: 63 if version['channel'] != channel_name: 64 continue 65 branch = version['version'].split('.')[2] 66 if branch not in branch_numbers: 67 branch_numbers[branch] = 0 68 else: 69 branch_numbers[branch] += 1 70 71 sorted_branches = sorted(branch_numbers.iteritems(), 72 None, 73 operator.itemgetter(1), 74 True) 75 self._object_store.Set(channel_name + '.' + self._base_path, 76 sorted_branches[0][0], 77 object_store.BRANCH_UTILITY) 78 79 return sorted_branches[0][0] 80