Skip to content

Commit 0f846ad

Browse files
committed
Add a script to transfer crates between users
1 parent 2fec57a commit 0f846ad

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ test = false
3434
name = "populate"
3535
test = false
3636

37+
[[bin]]
38+
name = "transfer-crates"
39+
test = false
40+
3741
[[test]]
3842
name = "all"
3943
path = "src/tests/all.rs"

src/bin/transfer-crates.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Transfer all crates from one user to another.
2+
//
3+
// Usage:
4+
// cargo run --bin transfer-crates from-user to-user
5+
6+
#![deny(warnings)]
7+
8+
extern crate cargo_registry;
9+
extern crate postgres;
10+
extern crate time;
11+
extern crate semver;
12+
13+
use std::env;
14+
use std::io;
15+
use std::io::prelude::*;
16+
17+
use cargo_registry::{Crate, env, User};
18+
use cargo_registry::Model;
19+
20+
#[allow(dead_code)]
21+
fn main() {
22+
let conn = postgres::Connection::connect(&env("DATABASE_URL")[..],
23+
postgres::SslMode::None).unwrap();
24+
{
25+
let tx = conn.transaction().unwrap();
26+
transfer(&tx);
27+
tx.set_commit();
28+
tx.finish().unwrap();
29+
}
30+
}
31+
32+
fn transfer(tx: &postgres::Transaction) {
33+
let from = match env::args().nth(1) {
34+
None => { println!("needs a from-user argument"); return }
35+
Some(s) => s,
36+
};
37+
let to = match env::args().nth(2) {
38+
None => { println!("needs a to-user argument"); return }
39+
Some(s) => s,
40+
};
41+
42+
let from = User::find_by_login(tx, &from).unwrap();
43+
let to = User::find_by_login(tx, &to).unwrap();
44+
45+
if from.avatar != to.avatar {
46+
println!("====================================================");
47+
println!("WARNING");
48+
println!("");
49+
println!("this may not be the same github user, different avatar urls");
50+
println!("");
51+
println!("from: {:?}", from.avatar);
52+
println!("to: {:?}", to.avatar);
53+
54+
get_confirm("continue?");
55+
}
56+
57+
println!("Are you sure you want to transfer crates from {} to {}",
58+
from.gh_login, to.gh_login);
59+
get_confirm("continue");
60+
61+
62+
let stmt = tx.prepare("SELECT * FROM crates WHERE user_id = $1")
63+
.unwrap();
64+
let crates = stmt.query(&[&from.id]).unwrap();
65+
for krate in crates.iter() {
66+
let krate = Crate::from_row(&krate);
67+
println!("transferring {}", krate.name);
68+
let owners = krate.owners(tx).unwrap();
69+
if owners.len() == 1 {
70+
let n = tx.execute("UPDATE crate_owners SET owner_id = $1
71+
WHERE owner_id = $2 AND crate_id = $3",
72+
&[&to.id, &from.id, &krate.id]).unwrap();
73+
assert_eq!(n, 1);
74+
} else {
75+
println!("error: not exactly one owner for {}", krate.name);
76+
return
77+
}
78+
79+
let n = tx.execute("UPDATE crates SET user_id = $1
80+
WHERE id = $2",
81+
&[&to.id, &krate.id]).unwrap();
82+
assert_eq!(n, 1);
83+
}
84+
85+
get_confirm("commit?");
86+
}
87+
88+
fn get_confirm(msg: &str) {
89+
print!("{} [y/N]: ", msg);
90+
io::stdout().flush().unwrap();
91+
let mut line = String::new();
92+
io::stdin().read_line(&mut line).unwrap();
93+
if !line.starts_with("y") {
94+
std::process::exit(0);
95+
}
96+
}

0 commit comments

Comments
 (0)