Skip to content

Commit 759fae6

Browse files
committed
---
yaml --- r: 105457 b: refs/heads/master c: 848f7b7 h: refs/heads/master i: 105455: 813deb3 v: v3
1 parent 6a592ef commit 759fae6

File tree

7 files changed

+384
-158
lines changed

7 files changed

+384
-158
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: d717d613e34482d7ddb738cea927900ca6601094
2+
refs/heads/master: 848f7b734ec88964879f5a3051b940d48469ce2e
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: b8601a3d8b91ad3b653d143307611f2f5c75617e
55
refs/heads/try: db814977d07bd798feb24f6b74c00800ef458a13

trunk/src/librustdoc/flock.rs

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Simple file-locking apis for each OS.
12+
//!
13+
//! This is not meant to be in the standard library, it does nothing with
14+
//! green/native threading. This is just a bare-bones enough solution for
15+
//! librustdoc, it is not production quality at all.
16+
17+
#[allow(non_camel_case_types)];
18+
19+
pub use self::imp::Lock;
20+
21+
#[cfg(unix)]
22+
mod imp {
23+
use std::libc;
24+
25+
#[cfg(target_os = "linux")]
26+
mod os {
27+
use std::libc;
28+
29+
pub struct flock {
30+
l_type: libc::c_short,
31+
l_whence: libc::c_short,
32+
l_start: libc::off_t,
33+
l_len: libc::off_t,
34+
l_pid: libc::pid_t,
35+
36+
// not actually here, but brings in line with freebsd
37+
l_sysid: libc::c_int,
38+
}
39+
40+
pub static F_WRLCK: libc::c_short = 1;
41+
pub static F_UNLCK: libc::c_short = 2;
42+
pub static F_SETLK: libc::c_int = 6;
43+
pub static F_SETLKW: libc::c_int = 7;
44+
}
45+
46+
#[cfg(target_os = "freebsd")]
47+
mod os {
48+
use std::libc;
49+
50+
pub struct flock {
51+
l_start: libc::off_t,
52+
l_len: libc::off_t,
53+
l_pid: libc::pid_t,
54+
l_type: libc::c_short,
55+
l_whence: libc::c_short,
56+
l_sysid: libc::c_int,
57+
}
58+
59+
pub static F_UNLCK: libc::c_short = 2;
60+
pub static F_WRLCK: libc::c_short = 3;
61+
pub static F_SETLK: libc::c_int = 12;
62+
pub static F_SETLKW: libc::c_int = 13;
63+
}
64+
65+
#[cfg(target_os = "macos")]
66+
mod os {
67+
use std::libc;
68+
69+
pub struct flock {
70+
l_start: libc::off_t,
71+
l_len: libc::off_t,
72+
l_pid: libc::pid_t,
73+
l_type: libc::c_short,
74+
l_whence: libc::c_short,
75+
76+
// not actually here, but brings in line with freebsd
77+
l_sysid: libc::c_int,
78+
}
79+
80+
pub static F_UNLCK: libc::c_short = 2;
81+
pub static F_WRLCK: libc::c_short = 3;
82+
pub static F_SETLK: libc::c_int = 8;
83+
pub static F_SETLKW: libc::c_int = 9;
84+
}
85+
86+
pub struct Lock {
87+
priv fd: libc::c_int,
88+
}
89+
90+
impl Lock {
91+
pub fn new(p: &Path) -> Lock {
92+
let fd = p.with_c_str(|s| unsafe {
93+
libc::open(s, libc::O_RDWR | libc::O_CREAT, libc::S_IRWXU)
94+
});
95+
assert!(fd > 0);
96+
let flock = os::flock {
97+
l_start: 0,
98+
l_len: 0,
99+
l_pid: 0,
100+
l_whence: libc::SEEK_SET as libc::c_short,
101+
l_type: os::F_WRLCK,
102+
l_sysid: 0,
103+
};
104+
let ret = unsafe {
105+
libc::fcntl(fd, os::F_SETLKW, &flock as *os::flock)
106+
};
107+
if ret == -1 {
108+
unsafe { libc::close(fd); }
109+
fail!("could not lock `{}`", p.display())
110+
}
111+
Lock { fd: fd }
112+
}
113+
}
114+
115+
impl Drop for Lock {
116+
fn drop(&mut self) {
117+
let flock = os::flock {
118+
l_start: 0,
119+
l_len: 0,
120+
l_pid: 0,
121+
l_whence: libc::SEEK_SET as libc::c_short,
122+
l_type: os::F_UNLCK,
123+
l_sysid: 0,
124+
};
125+
unsafe {
126+
libc::fcntl(self.fd, os::F_SETLK, &flock as *os::flock);
127+
libc::close(self.fd);
128+
}
129+
}
130+
}
131+
}
132+
133+
#[cfg(windows)]
134+
mod imp {
135+
use std::libc;
136+
use std::mem;
137+
use std::os::win32::as_utf16_p;
138+
use std::ptr;
139+
140+
static LOCKFILE_EXCLUSIVE_LOCK: libc::DWORD = 0x00000002;
141+
142+
extern "system" {
143+
fn LockFileEx(hFile: libc::HANDLE,
144+
dwFlags: libc::DWORD,
145+
dwReserved: libc::DWORD,
146+
nNumberOfBytesToLockLow: libc::DWORD,
147+
nNumberOfBytesToLockHigh: libc::DWORD,
148+
lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL;
149+
fn UnlockFileEx(hFile: libc::HANDLE,
150+
dwReserved: libc::DWORD,
151+
nNumberOfBytesToLockLow: libc::DWORD,
152+
nNumberOfBytesToLockHigh: libc::DWORD,
153+
lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL;
154+
}
155+
156+
pub struct Lock {
157+
priv handle: libc::HANDLE,
158+
}
159+
160+
impl Lock {
161+
pub fn new(p: &Path) -> Lock {
162+
let handle = as_utf16_p(p.as_str().unwrap(), |p| unsafe {
163+
libc::CreateFileW(p, libc::GENERIC_READ, 0, ptr::mut_null(),
164+
libc::CREATE_ALWAYS,
165+
libc::FILE_ATTRIBUTE_NORMAL,
166+
ptr::mut_null())
167+
});
168+
assert!(handle as uint != libc::INVALID_HANDLE_VALUE as uint);
169+
let mut overlapped: libc::OVERLAPPED = unsafe { mem::init() };
170+
let ret = unsafe {
171+
LockFileEx(handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0,
172+
&mut overlapped)
173+
};
174+
if ret == 0 {
175+
unsafe { libc::CloseHandle(handle); }
176+
fail!("could not lock `{}`", p.display())
177+
}
178+
Lock { handle: handle }
179+
}
180+
}
181+
182+
impl Drop for Lock {
183+
fn drop(&mut self) {
184+
let mut overlapped: libc::OVERLAPPED = unsafe { mem::init() };
185+
unsafe {
186+
UnlockFileEx(self.handle, 0, 100, 0, &mut overlapped);
187+
libc::CloseHandle(self.handle);
188+
}
189+
}
190+
}
191+
}

trunk/src/librustdoc/html/layout.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub fn render<T: fmt::Show, S: fmt::Show>(
3737
3838
<link href='http://fonts.googleapis.com/css?family=Oswald:700|Inconsolata:400,700'
3939
rel='stylesheet' type='text/css'>
40-
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}{krate}/main.css\">
40+
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}main.css\">
4141
4242
{favicon, select, none{} other{<link rel=\"shortcut icon\" href=\"#\" />}}
4343
</head>
@@ -74,13 +74,6 @@ pub fn render<T: fmt::Show, S: fmt::Show>(
7474
7575
<section class=\"footer\"></section>
7676
77-
<script>
78-
var rootPath = \"{root_path}\";
79-
</script>
80-
<script src=\"{root_path}{krate}/jquery.js\"></script>
81-
<script src=\"{root_path}{krate}/search-index.js\"></script>
82-
<script src=\"{root_path}{krate}/main.js\"></script>
83-
8477
<div id=\"help\" class=\"hidden\">
8578
<div class=\"shortcuts\">
8679
<h1>Keyboard shortcuts</h1>
@@ -111,6 +104,14 @@ pub fn render<T: fmt::Show, S: fmt::Show>(
111104
</p>
112105
</div>
113106
</div>
107+
108+
<script>
109+
var rootPath = \"{root_path}\";
110+
var currentCrate = \"{krate}\";
111+
</script>
112+
<script src=\"{root_path}jquery.js\"></script>
113+
<script src=\"{root_path}main.js\"></script>
114+
<script async src=\"{root_path}search-index.js\"></script>
114115
</body>
115116
</html>
116117
",

trunk/src/librustdoc/html/render.rs

Lines changed: 56 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
use std::fmt;
3737
use std::local_data;
3838
use std::io;
39-
use std::io::{fs, File, BufferedWriter};
39+
use std::io::{fs, File, BufferedWriter, MemWriter, BufferedReader};
4040
use std::str;
4141
use std::vec;
4242
use std::vec_ng::Vec;
@@ -283,48 +283,75 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
283283
};
284284
}
285285

286-
// Add all the static files
287-
let mut dst = cx.dst.join(krate.name.as_slice());
288-
try!(mkdir(&dst));
289-
try!(write(dst.join("jquery.js"),
290-
include_str!("static/jquery-2.1.0.min.js")));
291-
try!(write(dst.join("main.js"), include_str!("static/main.js")));
292-
try!(write(dst.join("main.css"), include_str!("static/main.css")));
293-
try!(write(dst.join("normalize.css"),
294-
include_str!("static/normalize.css")));
295-
296286
// Publish the search index
297-
{
298-
dst.push("search-index.js");
299-
let mut w = BufferedWriter::new(File::create(&dst).unwrap());
300-
let w = &mut w as &mut Writer;
301-
try!(write!(w, "var searchIndex = ["));
287+
let index = {
288+
let mut w = MemWriter::new();
289+
try!(write!(&mut w, "searchIndex['{}'] = [", krate.name));
302290
for (i, item) in cache.search_index.iter().enumerate() {
303291
if i > 0 {
304-
try!(write!(w, ","));
292+
try!(write!(&mut w, ","));
305293
}
306-
try!(write!(w, "\\{ty:\"{}\",name:\"{}\",path:\"{}\",desc:{}",
307-
item.ty, item.name, item.path,
308-
item.desc.to_json().to_str()));
294+
try!(write!(&mut w, "\\{ty:\"{}\",name:\"{}\",path:\"{}\",desc:{}",
295+
item.ty, item.name, item.path,
296+
item.desc.to_json().to_str()));
309297
match item.parent {
310298
Some(id) => {
311-
try!(write!(w, ",parent:'{}'", id));
299+
try!(write!(&mut w, ",parent:'{}'", id));
312300
}
313301
None => {}
314302
}
315-
try!(write!(w, "\\}"));
303+
try!(write!(&mut w, "\\}"));
316304
}
317-
try!(write!(w, "];"));
318-
try!(write!(w, "var allPaths = \\{"));
305+
try!(write!(&mut w, "];"));
306+
try!(write!(&mut w, "allPaths['{}'] = \\{", krate.name));
319307
for (i, (&id, &(ref fqp, short))) in cache.paths.iter().enumerate() {
320308
if i > 0 {
321-
try!(write!(w, ","));
309+
try!(write!(&mut w, ","));
322310
}
323-
try!(write!(w, "'{}':\\{type:'{}',name:'{}'\\}",
324-
id, short, *fqp.last().unwrap()));
311+
try!(write!(&mut w, "'{}':\\{type:'{}',name:'{}'\\}",
312+
id, short, *fqp.last().unwrap()));
325313
}
326-
try!(write!(w, "\\};"));
327-
try!(w.flush());
314+
try!(write!(&mut w, "\\};"));
315+
316+
str::from_utf8_owned(w.unwrap()).unwrap()
317+
};
318+
319+
// Write out the shared files. Note that these are shared among all rustdoc
320+
// docs placed in the output directory, so this needs to be a synchronized
321+
// operation with respect to all other rustdocs running around.
322+
{
323+
try!(mkdir(&cx.dst));
324+
let _lock = ::flock::Lock::new(&cx.dst.join(".lock"));
325+
326+
// Add all the static files. These may already exist, but we just
327+
// overwrite them anyway to make sure that they're fresh and up-to-date.
328+
try!(write(cx.dst.join("jquery.js"),
329+
include_str!("static/jquery-2.1.0.min.js")));
330+
try!(write(cx.dst.join("main.js"), include_str!("static/main.js")));
331+
try!(write(cx.dst.join("main.css"), include_str!("static/main.css")));
332+
try!(write(cx.dst.join("normalize.css"),
333+
include_str!("static/normalize.css")));
334+
335+
// Update the search index
336+
let dst = cx.dst.join("search-index.js");
337+
let mut all_indexes = Vec::new();
338+
all_indexes.push(index);
339+
if dst.exists() {
340+
for line in BufferedReader::new(File::open(&dst)).lines() {
341+
let line = try!(line);
342+
if !line.starts_with("searchIndex") { continue }
343+
if line.starts_with(format!("searchIndex['{}']", krate.name)) {
344+
continue
345+
}
346+
all_indexes.push(line);
347+
}
348+
}
349+
let mut w = try!(File::create(&dst));
350+
try!(writeln!(&mut w, r"var searchIndex = \{\}; var allPaths = \{\};"));
351+
for index in all_indexes.iter() {
352+
try!(writeln!(&mut w, "{}", *index));
353+
}
354+
try!(writeln!(&mut w, "initSearch(searchIndex);"));
328355
}
329356

330357
// Render all source files (this may turn into a giant no-op)

0 commit comments

Comments
 (0)