@@ -18,7 +18,7 @@ use url::Url;
1818
1919use super :: super :: USER_AGENT ;
2020use ext:: hyper:: header:: Link ;
21- use gist:: { self , Gist } ;
21+ use gist:: { self , Datum , Gist } ;
2222use util:: { mark_executable, symlink_file} ;
2323use super :: Host ;
2424
@@ -42,17 +42,15 @@ impl Host for GitHub {
4242 /// If the gist hasn't been downloaded already, a clone of the gist's Git repo is performed.
4343 /// Otherwise, it's just a simple Git pull.
4444 fn fetch_gist ( & self , gist : & Gist ) -> io:: Result < ( ) > {
45- if gist. uri . host_id != "gh" {
46- return Err ( io:: Error :: new ( io:: ErrorKind :: InvalidData , format ! (
47- "expected a GitHub Gist, but got a '{}' one" , gist. uri. host_id) ) ) ;
48- }
49-
45+ try!( ensure_github_gist ( gist) ) ;
5046 let gist = try!( resolve_gist ( gist) ) ;
47+
5148 if gist. is_local ( ) {
5249 try!( update_gist ( gist) ) ;
5350 } else {
5451 try!( clone_gist ( gist) ) ;
5552 }
53+
5654 Ok ( ( ) )
5755 }
5856
@@ -65,6 +63,29 @@ impl Host for GitHub {
6563 url. set_path ( & format ! ( "{}/{}" , gist. uri. owner, gist. id. as_ref( ) . unwrap( ) ) ) ;
6664 Ok ( url. into_string ( ) )
6765 }
66+
67+ /// Return a structure with gist metadata.
68+ fn gist_info ( & self , gist : & Gist ) -> io:: Result < Option < gist:: Info > > {
69+ try!( ensure_github_gist ( gist) ) ;
70+ let gist = try!( resolve_gist ( gist) ) ;
71+
72+ let info = try!( get_gist_info ( gist. id . as_ref ( ) . unwrap ( ) ) ) ;
73+
74+ // Build the gist::Info structure from known keys in the gist info JSON.
75+ const INFO_FIELDS : & ' static [ ( Datum , & ' static str ) ] = & [
76+ ( Datum :: Id , "id" ) ,
77+ ( Datum :: Description , "description" ) ,
78+ ( Datum :: Url , "html_url" ) ,
79+ ( Datum :: CreatedAt , "created_at" ) ,
80+ ( Datum :: UpdatedAt , "updated_at" ) ,
81+ ] ;
82+ let mut result = gist:: InfoBuilder :: new ( ) ;
83+ for & ( datum, field) in INFO_FIELDS {
84+ result. set ( datum, info[ field] . as_string ( ) . unwrap ( ) ) ;
85+ }
86+ result. set ( Datum :: Owner , info[ "owner" ] [ "login" ] . as_string ( ) . unwrap ( ) ) ;
87+ Ok ( Some ( result. build ( ) ) )
88+ }
6889}
6990
7091/// Base URL to gist HTML pages.
@@ -158,24 +179,10 @@ fn clone_gist<G: AsRef<Gist>>(gist: G) -> io::Result<()> {
158179 // Talk to GitHub to obtain the URL that we can clone the gist from
159180 // as a Git repository.
160181 let clone_url = {
161- let http = Client :: new ( ) ;
162-
163- let gist_url = {
164- let mut url = Url :: parse ( API_URL ) . unwrap ( ) ;
165- url. set_path ( & format ! ( "gists/{}" , gist. id. as_ref( ) . unwrap( ) ) ) ;
166- url. into_string ( )
167- } ;
168-
169- debug ! ( "Getting GitHub gist info from {}" , gist_url) ;
170- let mut resp = try!( http. get ( & gist_url)
171- . header ( UserAgent ( USER_AGENT . clone ( ) ) )
172- . send ( )
173- . map_err ( |e| io:: Error :: new ( io:: ErrorKind :: Other , e) ) ) ;
174- let gist_info_json = read_json ( & mut resp) ;
175-
176- let clone_url = gist_info_json[ "git_pull_url" ] . as_string ( ) . unwrap ( ) . to_owned ( ) ;
182+ let gist_info = try!( get_gist_info ( & gist. id . as_ref ( ) . unwrap ( ) ) ) ;
183+ let clone_url = gist_info[ "git_pull_url" ] . as_string ( ) . unwrap ( ) . to_owned ( ) ;
177184 trace ! ( "GitHub gist #{} has a git_pull_url=\" {}\" " ,
178- gist_info_json [ "id" ] . as_string( ) . unwrap( ) , clone_url) ;
185+ gist_info [ "id" ] . as_string( ) . unwrap( ) , clone_url) ;
179186 clone_url
180187 } ;
181188
@@ -263,8 +270,37 @@ fn list_gists(owner: &str) -> Vec<Gist> {
263270}
264271
265272
273+ /// Retrieve information/metadata about a gist.
274+ /// Returns a Json object with the parsed GitHub response.
275+ fn get_gist_info ( gist_id : & str ) -> io:: Result < Json > {
276+ let http = Client :: new ( ) ;
277+
278+ let gist_url = {
279+ let mut url = Url :: parse ( API_URL ) . unwrap ( ) ;
280+ url. set_path ( & format ! ( "gists/{}" , gist_id) ) ;
281+ url. into_string ( )
282+ } ;
283+
284+ debug ! ( "Getting GitHub gist info from {}" , gist_url) ;
285+ let mut resp = try!( http. get ( & gist_url)
286+ . header ( UserAgent ( USER_AGENT . clone ( ) ) )
287+ . send ( )
288+ . map_err ( |e| io:: Error :: new ( io:: ErrorKind :: Other , e) ) ) ;
289+ Ok ( read_json ( & mut resp) )
290+ }
291+
292+
266293// Utility functions
267294
295+ /// Check if given Gist is a GitHub gist. Invoke using try!().
296+ fn ensure_github_gist ( gist : & Gist ) -> io:: Result < ( ) > {
297+ if gist. uri . host_id != "gh" {
298+ return Err ( io:: Error :: new ( io:: ErrorKind :: InvalidData , format ! (
299+ "expected a GitHub Gist, but got a '{}' one" , gist. uri. host_id) ) ) ;
300+ }
301+ Ok ( ( ) )
302+ }
303+
268304/// Read HTTP response from hype and parse it as JSON.
269305fn read_json ( response : & mut Response ) -> Json {
270306 let mut body = match response. headers . get :: < ContentLength > ( ) {
0 commit comments