diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/github.rs | 1 | ||||
-rw-r--r-- | src/main.rs | 147 |
2 files changed, 121 insertions, 27 deletions
diff --git a/src/github.rs b/src/github.rs index 5289a0d..a3bb74e 100644 --- a/src/github.rs +++ b/src/github.rs @@ -47,6 +47,7 @@ pub struct Repo { pub default_branch: String, pub size: u64, pub updated_at: String, + pub pushed_at: String, } impl Repo { diff --git a/src/main.rs b/src/main.rs index 2de21b9..a776070 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,7 +32,7 @@ use multi_error::MultiError; use std::env; use std::fs; -use std::io; +use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::process; @@ -109,8 +109,35 @@ fn run() -> Result<(), MultiError> { let base_cgitrc = opt_matches.opt_str("cgitrc") .map(|s| PathBuf::from(s)); - let repos = github::fetch_repos(username) - .context("unable to fetch GitHub repositories")?; + // let repos = github::fetch_repos(username) + // .context("unable to fetch GitHub repositories")?; + + let repos = vec![ + github::Repo { + id: 5924490, + name: "THWAP".to_owned(), + description: None, + fork: false, + git_url: "git://github.com/teddywing/THWAP.git".to_owned(), + default_branch: "master".to_owned(), + size: 48, + updated_at: "2013-01-12T09:09:38Z".to_owned(), + pushed_at: "2012-09-23T17:45:14Z".to_owned(), + }, + github::Repo { + id: 158463778, + name: "youtube-turn-off-annotations".to_owned(), + description: Some( + "A user script that turns off annotations on YouTube videos".to_owned(), + ), + fork: false, + git_url: "git://github.com/teddywing/youtube-turn-off-annotations.git".to_owned(), + default_branch: "master".to_owned(), + size: 17, + updated_at: "2018-11-20T23:44:31Z".to_owned(), + pushed_at: "2018-11-20T23:44:29Z".to_owned(), + }, + ]; let db = database::Db::connect(&database_file) .context("unable to connect to database")?; @@ -282,22 +309,27 @@ fn update<P: AsRef<Path>>( Ok(()) } -/// Set the mtime of the repository to GitHub's `updated_at` time. +/// Set the mtime of the repository to GitHub's `pushed_at` time. /// /// Used for CGit "age" sorting. fn update_mtime<P: AsRef<Path>>( repo_path: P, repo: &github::Repo, ) -> anyhow::Result<()> { + let update_time = filetime::FileTime::from_system_time( + DateTime::parse_from_rfc3339(&repo.pushed_at) + .with_context(|| format!( + "unable to parse update time from '{}'", + &repo.pushed_at, + ))? + .into() + ); + let default_branch_ref = repo_path .as_ref() .join("refs/heads") .join(&repo.default_branch); - let update_time = filetime::FileTime::from_system_time( - DateTime::parse_from_rfc3339(&repo.updated_at)?.into() - ); - // Try updating times on the default ref. match filetime::set_file_times( &default_branch_ref, @@ -305,28 +337,34 @@ fn update_mtime<P: AsRef<Path>>( update_time, ) { Ok(_) => Ok(()), - Err(e) => match e.kind() { + Err(e) if e.kind() == io::ErrorKind::NotFound => { // If the default ref file doesn't exist, update times on the // 'packed-refs' file. - io::ErrorKind::NotFound => { - let packed_refs_path = repo_path - .as_ref() - .join("packed-refs"); - - Ok( - filetime::set_file_times( - &packed_refs_path, - update_time, - update_time, - ) - .with_context(|| format!( - "unable to set mtime on '{}'", - &packed_refs_path.display(), - ))? - ) - }, - _ => Err(e), + let packed_refs_path = repo_path + .as_ref() + .join("packed-refs"); + + match filetime::set_file_times( + &packed_refs_path, + update_time, + update_time, + ) { + Ok(_) => Ok(()), + Err(e) if e.kind() == io::ErrorKind::NotFound => { + // In the absence of a 'packed-refs' file, create a CGit + // agefile and add the update time to it. + Ok(set_agefile_time(&repo_path, &repo.pushed_at)?) + }, + Err(e) => Err(e), + } + .with_context(|| format!( + "unable to set mtime on '{}'", + &packed_refs_path.display(), + ))?; + + Ok(()) }, + Err(e) => Err(e), } .with_context(|| format!( "unable to set mtime on '{}'", @@ -335,3 +373,58 @@ fn update_mtime<P: AsRef<Path>>( Ok(()) } + +/// Write `update_time` into the repo's `info/web/last-modified` file. +fn set_agefile_time<P: AsRef<Path>>( + repo_path: P, + update_time: &str, +) -> anyhow::Result<()> { + let agefile_dir = repo_path.as_ref().join("info/web"); + fs::DirBuilder::new() + .create(&agefile_dir) + .with_context(|| format!( + "unable to create directory '{}'", + &agefile_dir.display(), + ))?; + + let agefile_path = agefile_dir.join("last-modified"); + let mut agefile = fs::OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(&agefile_path) + .with_context(|| format!( + "unable to open '{}'", + &agefile_path.display(), + ))?; + + writeln!(agefile, "{}", &update_time) + .with_context(|| format!( + "unable to write to '{}'", + &agefile_path.display(), + ))?; + + let cgitrc_path = repo_path + .as_ref() + .join("cgitrc"); + let mut cgitrc_file = fs::OpenOptions::new() + .append(true) + .create(true) + .open(&cgitrc_path) + .with_context(|| format!( + "unable to open '{}'", + &cgitrc_path.display(), + ))?; + + writeln!( + cgitrc_file, + "{}", + "agefile=info/web/last-modified", + ) + .with_context(|| format!( + "unable to write to '{}'", + &cgitrc_path.display(), + ))?; + + Ok(()) +} |