Matthew Turk avatar Matthew Turk committed 03f5926

Adding bbfollowers command, as well as updating the _bb_apicall function to
accept password-free API calls and to not require a POST method

Comments (0)

Files changed (1)

 import urllib
 import urllib2
 import urlparse
+import json
 
 # utility functions
 
             #json = urllib.urlopen(
             #    'http://api.bitbucket.org/1.0/repositories/%s/' % name).read()
 
-def _bb_apicall(ui, endpoint, data):
+def _bb_apicall(ui, endpoint, data, use_pass = True):
     uri = 'https://api.bitbucket.org/1.0/%s/' % endpoint
     # since bitbucket doesn't return the required WWW-Authenticate header when
     # making a request without Authorization, we cannot use the standard urllib2
     # auth handlers; we have to add the requisite header from the start
-    req = urllib2.Request(uri, urllib.urlencode(data))
-    # at least re-use Mercurial's password query
-    passmgr = url.passwordmgr(ui)
-    passmgr.add_password(None, uri, get_username(ui), '')
-    upw = '%s:%s' % passmgr.find_user_password(None, uri)
-    req.add_header('Authorization', 'Basic %s' % base64.b64encode(upw).strip())
+    if data is not None:
+        data = urllib.urlencode(data)
+    req = urllib2.Request(uri, data)
+    #ui.status("Accessing %s" % uri)
+    if use_pass:
+        # at least re-use Mercurial's password query
+        passmgr = url.passwordmgr(ui)
+        passmgr.add_password(None, uri, get_username(ui), '')
+        upw = '%s:%s' % passmgr.find_user_password(None, uri)
+        req.add_header('Authorization', 'Basic %s' % base64.b64encode(upw).strip())
     return urllib2.urlopen(req).read()
 
 def bb_create(ui, reponame, **opts):
     ui.write('repository created, cloning...\n')
     commands.clone(ui, 'bb://' + reponame)
 
+def bb_followers(ui, repo, **opts):
+    '''list all followers of this repo at bitbucket
+
+    An explicit bitbucket reponame (``username/repo``) can be given with the
+    ``-n`` option.
+    '''
+    reponame = get_bbreponame(ui, repo, opts)
+    ui.status('getting followers list\n')
+    retval = _bb_apicall(ui, 'repositories/%s/followers' % (reponame),
+                         None, False)
+    followers = json.loads(retval)
+    ui.write("List of followers:\n")
+    for follower in sorted(followers.get(u'followers', [])):
+        ui.write("    %s (%s %s)\n" % (
+            follower['username'],
+            follower['first_name'],
+            follower['last_name']))
 
 def clone(orig, ui, source, dest=None, **opts):
     if source[:2] == 'bb' and ':' in source:
           ('l', 'language', '', 'programming language'),
           ('w', 'website', '', 'website of the project'),
           ],
-         'hg bbcreate [-d desc] [-l lang] [-w site] reponame')
+         'hg bbcreate [-d desc] [-l lang] [-w site] reponame'),
+    'bbfollowers':
+        (bb_followers,
+         [('n', 'reponame', '',
+           'name of the repo at bitbucket (else guessed from repo dir)'),
+          ],
+         'hg bbcreate [-d desc] [-l lang] [-w site] reponame'),
 }
 
 commands.norepo += ' bbcreate'
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.