1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// wiki_pages_create_or_update.rs
// Wiki page creation/update example.
use anyhow::Result;
use azure_devops_rust_api::wiki::{self, pages};
use std::env;
mod utils;
#[tokio::main]
async fn main() -> Result<()> {
// Initialize logging
env_logger::init();
// Get authentication credential
let credential = utils::get_credential();
// Get ADO configuration via environment variables
let organization = env::var("ADO_ORGANIZATION").expect("Must define ADO_ORGANIZATION");
let project = env::var("ADO_PROJECT").expect("Must define ADO_PROJECT");
// Get wiki params based on arguments
let wiki_id = env::args()
.nth(1)
.expect("Usage: Wiki ID to create/update a page under <wiki-id>");
let wiki_page_path = env::args()
.nth(2)
.expect("Usage: Wiki page path to create/update <wiki-page-path>");
let wiki_content = env::args()
.nth(3)
.expect("Usage: Wiki content to be inserted into the page <wiki-content>");
// Create a wiki pages client
let wiki_pages_client = wiki::ClientBuilder::new(credential).build().pages_client();
// To update an existing wiki page the page version, called an eTag, must be supplied in an `If-Match` header. NB: the RequestBuilder will insert this header for you when you call it with the `eTag`.
// This function call returns `Some(String)` containing the eTag if the pages exists, otherwise
// it will return `None` indicating that the page needs to be created.
let op_etag: Option<String> = get_wiki_page_etag(
&wiki_pages_client,
&wiki_page_path,
&organization,
&project,
&wiki_id,
)
.await;
// The content to be displayed on the page
let wiki_body = wiki::models::WikiPageCreateOrUpdateParameters {
content: Some(wiki_content),
};
// Based on whether the page exists either update or create
match op_etag {
Some(etag) => {
println!("Updating wiki page...");
match wiki_pages_client
.create_or_update(
organization,
wiki_body,
project,
wiki_id,
wiki_page_path,
etag,
)
.await
{
Ok(p) => println!("Page updated: {:?}", p.remote_url),
Err(e) => panic!("Failed to update wiki page: {}", e),
}
}
None => {
println!("Creating wiki page...");
match wiki_pages_client
.create_or_update(
organization,
wiki_body,
project,
wiki_id,
wiki_page_path,
"a123", // fake version value, unused in creation operation
)
.await
{
Ok(p) => println!("Page created: {:?}", p.remote_url),
Err(e) => panic!("Failed to create wiki page: {}", e),
}
}
}
Ok(())
}
/// Using a [pages::Client] attempt to retrieve the version (`eTag`) of a wiki page at `page_path`.
/// The `eTag` is required when updating an existing wiki page.
///
/// If the page does not exist [None] is returned and in such cases the page needs to be created
async fn get_wiki_page_etag(
client: &pages::Client,
page_path: &String,
organisation: &String,
project: &String,
wiki_id: &String,
) -> Option<String> {
match client
.get_page(organisation, project, wiki_id)
.path(page_path)
.send()
.await
{
Ok(r) => {
let etag = r.headers().e_tag().unwrap().to_owned();
println!("Etag for page {}, {}", page_path, etag);
Some(etag)
}
Err(e) => {
// If the response is a 404 then we need to create the page
if e.as_http_error()
.expect("Failed cast to http error")
.status()
.canonical_reason()
== "Not Found"
{
println!("Wiki page does not exist");
None
} else {
panic!("Failed to retrieve etag: {}", e)
}
}
}
}