types.rs 69.1 KB
Newer Older
1
2
3
4
5
6
7
8
// Copyright 2016 Kitware, Inc.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

Ben Boeckel's avatar
Ben Boeckel committed
9
10
11
12
13
14
15
16
//! API entities
//!
//! These entities are exposed by Gitlab via its API.
//!
//! There are some places where Gitlab does not completely specify its types. This causes
//! problems when the types and names change inside of those. If found, issues should be filed
//! upstream.

17
18
19
20
21
22
23
24
25
26
27
28
29
extern crate chrono;
use self::chrono::{DateTime, NaiveDate, UTC};

extern crate serde;
use self::serde::{Deserialize, Deserializer, Serialize, Serializer};
use self::serde::de::{Error, Unexpected};

extern crate serde_json;
use self::serde_json::Value;

use std::fmt::{self, Display, Formatter};

// This is only used in internal API calls.
30
//#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
31
32
33
34
35
36
//#[derive(Serialize, Deserialize, Debug, Clone)]
//pub struct UserSafe {
//    pub username: String,
//    pub name: String,
//}

37
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
/// Type-safe user ID.
pub struct UserId(u64);
impl_id!(UserId);

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// The states a user account can be in.
pub enum UserState {
    /// The user is active and may perform actions.
    Active,
    /// Blocked from logging in.
    Blocked,
    /// Blocked from logging in via LDAP.
    LdapBlocked,
}
enum_serialize!(UserState -> "user state",
    Active => "active",
    Blocked => "blocked",
    LdapBlocked => "ldap_blocked",
);

59
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
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
#[derive(Serialize, Deserialize, Debug, Clone)]
/// Basic user information.
pub struct UserBasic {
    /// The username.
    pub username: String,
    /// The display name.
    pub name: String,
    /// The user's ID.
    pub id: UserId,
    /// The state of the user account.
    pub state: UserState,
    /// The URL of the user's avatar.
    pub avatar_url: String,
    /// The URL of the user's profile page.
    pub web_url: String,
}

/// A unifying trait for all user types.
///
/// This is used to allow (direct) user queries to return the right information because
/// administrator users receive additional information for all user queries versus
/// non-administrator users.
pub trait UserResult: Deserialize {}
impl<T: Deserialize + Into<UserBasic>> UserResult for T {}

85
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
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
133
134
#[derive(Serialize, Deserialize, Debug, Clone)]
/// More detailed information only accessible to administrators.
pub struct User {
    /// The username.
    pub username: String,
    /// The display name.
    pub name: String,
    /// The user's ID.
    pub id: UserId,
    /// The state of the user account.
    pub state: UserState,
    /// The URL of the user's avatar.
    pub avatar_url: String,
    /// The URL of the user's profile page.
    pub web_url: String,
    /// When the account was created.
    pub created_at: DateTime<UTC>,
    /// Whether the user is an administrator or not.
    pub is_admin: bool,
    /// Self-described biography of the user.
    pub bio: Option<String>,
    /// Geographic location of the user.
    pub location: Option<String>,

    /// Skype contact information.
    pub skype: String,
    /// LinkedIn contact information.
    pub linkedin: String,
    /// Twitter contact information.
    pub twitter: String,
    /// Custom URL for the user's website.
    pub website_url: String,
    /// Organization the user belongs to.
    pub organization: Option<String>,
}

impl From<User> for UserBasic {
    fn from(user: User) -> Self {
        UserBasic {
            username: user.username,
            name: user.name,
            id: user.id,
            state: user.state,
            avatar_url: user.avatar_url,
            web_url: user.web_url,
        }
    }
}

135
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
136
137
138
139
140
141
142
143
144
#[derive(Serialize, Deserialize, Debug, Clone)]
/// External authentication tokens.
pub struct Identity {
    /// The provider of the token.
    pub provider: String,
    /// The UID for the provider.
    pub extern_uid: String,
}

145
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
146
147
148
149
150
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
/// Type-safe theme ID.
pub struct ThemeId(u64);
impl_id!(ThemeId);

151
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
152
153
154
155
156
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
/// Type-safe color scheme ID.
pub struct ColorSchemeId(u64);
impl_id!(ColorSchemeId);

157
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#[derive(Serialize, Deserialize, Debug, Clone)]
/// Full user structure information.
pub struct UserPublic {
    /// The username.
    pub username: String,
    /// The display name.
    pub name: String,
    /// The user's ID.
    pub id: UserId,
    /// The state of the user account.
    pub state: UserState,
    /// The URL of the user's avatar.
    pub avatar_url: String,
    /// The URL of the user's profile page.
    pub web_url: String,
    /// When the account was created.
    pub created_at: DateTime<UTC>,
    /// Whether the user is an administrator or not.
    pub is_admin: bool,
    /// Self-described biography of the user.
    pub bio: Option<String>,
    /// Geographic location of the user.
    pub location: Option<String>,

    /// Skype contact information.
    pub skype: String,
    /// LinkedIn contact information.
    pub linkedin: String,
    /// Twitter contact information.
    pub twitter: String,
    /// Custom URL for the user's website.
    pub website_url: String,
    /// Organization the user belongs to.
    pub organization: Option<String>,

    /// When the user last logged in.
    pub last_sign_in_at: Option<DateTime<UTC>>,
    /// When the user's account was confirmed.
    pub confirmed_at: DateTime<UTC>,
    /// The primary email address for the user.
    pub email: String,

    /// The theme used by the user.
    pub theme_id: ThemeId,
    /// The color scheme used by the user.
    pub color_scheme_id: ColorSchemeId,
    /// The number of projects the user may create.
    pub projects_limit: u64,
    /// When the user's current session started.
    pub current_sign_in_at: Option<DateTime<UTC>>,

    /// List of identities associated with the user.
    pub identities: Vec<Identity>,

    /// Whether the user can create groups.
    pub can_create_group: bool,
    /// Whether the user can create a new project.
    pub can_create_project: bool,
    /// Whether the user has two-factor authentication enabled.
    pub two_factor_enabled: bool,
    /// Whether the account is externally controlled.
    pub external: bool,
}

impl From<UserPublic> for UserBasic {
    fn from(user: UserPublic) -> Self {
        UserBasic {
            username: user.username,
            name: user.name,
            id: user.id,
            state: user.state,
            avatar_url: user.avatar_url,
            web_url: user.web_url,
        }
    }
}

impl From<UserPublic> for User {
    fn from(user: UserPublic) -> Self {
        User {
            username: user.username,
            name: user.name,
            id: user.id,
            state: user.state,
            avatar_url: user.avatar_url,
            web_url: user.web_url,
            created_at: user.created_at,
            is_admin: user.is_admin,
            bio: user.bio,
            location: user.location,
            skype: user.skype,
            linkedin: user.linkedin,
            twitter: user.twitter,
            website_url: user.website_url,
            organization: user.organization,
        }
    }
}

257
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
258
259
260
261
262
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
/// Type-safe email ID.
pub struct EmailId(u64);
impl_id!(EmailId);

263
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
264
265
266
267
268
269
270
271
272
#[derive(Serialize, Deserialize, Debug, Clone)]
/// Email address.
pub struct Email {
    /// ID of the email.
    pub id: EmailId,
    /// The email address.
    pub email: String,
}

273
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
274
275
276
277
278
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
/// Type-safe hook ID.
pub struct HookId(u64);
impl_id!(HookId);

279
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#[derive(Serialize, Deserialize, Debug, Clone)]
/// A web hook to notify of events.
pub struct Hook {
    /// The ID of the hook.
    pub id: HookId,
    /// The URL to contact.
    pub url: String,
    /// When the hook was created.
    pub created_at: DateTime<UTC>,
    /// Whether the hook is contacted for push events.
    pub push_events: bool,
    /// Whether the hook is contacted for tag push events.
    pub tag_push_events: bool,
    /// Whether the communication with the hook is verified using TLS certificates.
    pub enable_ssl_verification: bool,
}

297
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
#[derive(Serialize, Deserialize, Debug, Clone)]
/// A web hook to notify of project events.
pub struct ProjectHook {
    /// The ID of the hook.
    pub id: HookId,
    /// The URL to contact.
    pub url: String,
    /// When the hook was created.
    pub created_at: DateTime<UTC>,
    /// The project associated with the hook.
    pub project_id: ProjectId,
    /// Whether the hook is contacted for push events.
    pub push_events: bool,
    /// Whether the hook is contacted for tag push events.
    pub tag_push_events: bool,
    /// Whether the hook is contacted for issue events.
    pub issues_events: bool,
    /// Whether the hook is contacted for merge request events.
    pub merge_requests_events: bool,
    /// Whether the hook is contacted for note events.
    pub note_events: bool,
    /// Whether the communication with the hook is verified using TLS certificates.
    pub enable_ssl_verification: bool,
    /// Whether the hook is contacted for build events.
    pub build_events: bool,
    /// Whether the hook is contacted for pipeline events.
    pub pipeline_events: bool,
    /// Whether the hook is contacted for wiki page events.
    pub wiki_page_events: bool,
}

impl From<ProjectHook> for Hook {
    fn from(hook: ProjectHook) -> Self {
        Hook {
            id: hook.id,
            url: hook.url,
            created_at: hook.created_at,
            push_events: hook.push_events,
            tag_push_events: hook.tag_push_events,
            enable_ssl_verification: hook.enable_ssl_verification,
        }
    }
}

#[derive(Debug, Default, Clone, Copy)]
/// The events a webhook listener may receive.
pub struct WebhookEvents {
    /// Whether to receive build events of not.
    build: bool,
    /// Whether to receive issue events of not.
    issues: bool,
    /// Whether to receive merge request events of not.
    merge_requests: bool,
    /// Whether to receive note (comment) events of not.
    note: bool,
    /// Whether to receive pipeline events of not.
    pipeline: bool,
    /// Whether to receive push events of not.
    push: bool,
    /// Whether to receive wiki events of not.
    wiki_page: bool,
}

impl WebhookEvents {
    /// Create a new, empty webhook event set.
    pub fn new() -> Self {
        WebhookEvents {
            build: false,
            issues: false,
            merge_requests: false,
            note: false,
            pipeline: false,
            push: false,
            wiki_page: false,
        }
    }

    with_event!{with_build, build}
    with_event!{with_issues, issues}
    with_event!{with_merge_requests, merge_requests}
    with_event!{with_note, note}
    with_event!{with_pipeline, pipeline}
    with_event!{with_push, push}
    with_event!{with_wiki_page, wiki_page}

    get_event!{build}
    get_event!{issues}
    get_event!{merge_requests}
    get_event!{note}
    get_event!{pipeline}
    get_event!{push}
    get_event!{wiki_page}
}

392
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
393
394
395
396
397
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
/// Type-safe project ID.
pub struct ProjectId(u64);
impl_id!(ProjectId);

398
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
#[derive(Serialize, Deserialize, Debug, Clone)]
/// Basic project information.
pub struct BasicProjectDetails {
    /// The ID of the project.
    pub id: ProjectId,
    /// The display name of the project.
    pub name: String,
    /// The display name of the project with the namespace.
    pub name_with_namespace: String,
    /// The path to the project's repository.
    pub path: String,
    /// The path to the project's repository with its namespace.
    pub path_with_namespace: String,
    /// The URL to the main page of the repository.
    pub http_url_to_repo: String,
    /// The URL to the main page of the repository.
    pub web_url: String,
}

/// Visibility levels of projects.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum VisibilityLevel {
    /// The project is visible to anonymous users.
    Public = 20,
    /// The project is visible to logged in users.
    Internal = 10,
    /// The project is visible only to users with explicit access.
    Private = 0,
}

impl From<VisibilityLevel> for u64 {
    fn from(visibility: VisibilityLevel) -> Self {
        match visibility {
            VisibilityLevel::Public => 20,
            VisibilityLevel::Internal => 10,
            VisibilityLevel::Private => 0,
        }
    }
}

impl Display for VisibilityLevel {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", Into::<u64>::into(self.clone()))
    }
}

// TODO: enum for NotificationLevel

447
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
448
449
450
451
452
453
454
455
456
457
458
#[derive(Serialize, Deserialize, Debug, Clone)]
/// Structure for a group a project has been shared with.
pub struct SharedGroup {
    /// The ID of the group.
    pub group_id: GroupId,
    /// The name of the group.
    pub group_name: String,
    /// The access level of the group.
    pub group_access_level: u64,
}

459
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
460
461
462
463
464
465
466
467
468
469
470
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
/// Access information to a project.
// Called `MemberAccess` in entities.rb, but it is just a base class for `ProjectAccess` and
// `GroupAccess`. Combine them here.
pub struct MemberAccess {
    /// The access level of the membership (see `VisibilityLevel`).
    pub access_level: u64,
    /// The notification level of the current user.
    pub notification_level: Option<u64>,
}

471
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
472
473
474
475
476
477
478
479
480
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
/// Permissions granted to the current user to a project.
pub struct Permissions {
    /// The access granted by the project to the current user.
    pub project_access: Option<MemberAccess>,
    /// The access granted by the group to the current user.
    pub group_access: Option<MemberAccess>,
}

481
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
482
483
484
485
486
487
488
#[derive(Serialize, Deserialize, Debug, Clone)]
/// The avatar of a project's namespace.
pub struct ProjectNamespaceAvatar {
    /// The URL of the namespace avatar.
    pub url: Option<String>,
}

489
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
#[derive(Serialize, Deserialize, Debug, Clone)]
/// Project information.
pub struct Project {
    /// The ID of the project.
    pub id: ProjectId,
    /// The description of the project.
    pub description: Option<String>,
    /// The default branch for the project.
    pub default_branch: Option<String>,
    /// A list of tags for the project.
    pub tag_list: Vec<String>,
    /// Whether the project is publicly visible or not.
    pub public: bool,
    /// Whether the project is archived or not.
    pub archived: bool,
    /// Integral value for the project's visibility.
    pub visibility_level: u64,
    /// The URL to clone the repository over SSH.
    pub ssh_url_to_repo: String,
    /// The URL to clone the repository over HTTPS.
    pub http_url_to_repo: String,
    /// The URL for the project's homepage.
    pub web_url: String,
    /// The owner of the project (`None` for a group-owned project).
    pub owner: Option<UserBasic>,
    /// The display name of the project.
    pub name: String,
    /// The display name of the project with the namespace.
    pub name_with_namespace: String,
    /// The path to the project's repository.
    pub path: String,
    /// The path to the project's repository with its namespace.
    pub path_with_namespace: String,
    /// Whether the continuous integration container registry is enabled.
    ///
    /// This is supposed to be just `bool`, but projects created before the registry was
    /// supported appear to return `null`.
    pub container_registry_enabled: Option<bool>,
    /// When the repository was created.
    pub created_at: DateTime<UTC>,
    /// When the last activity on the project occurred.
    pub last_activity_at: DateTime<UTC>,
    /// Whether continuous integration shared runners are enabled.
    pub shared_runners_enabled: bool,
    /// Whether LFS object storage is enabled.
    pub lfs_enabled: bool,
    /// The user who created the repository.
    pub creator_id: UserId,
    /// The namespace the project lives in.
    pub namespace: Namespace,
    /// If the project is a fork, details about it.
    pub forked_from_project: Option<BasicProjectDetails>,
    /// The URL to the project avatar.
    pub avatar_url: Option<String>,
    /// The number of stars for the project.
    pub star_count: u64,
    /// The number of forks.
    pub forks_count: u64,
    /// The number of open issues (if issues are enabled).
    pub open_issues_count: Option<u64>,
    /// The continuous integration runner token (if enabled).
    pub runners_token: Option<String>,
    /// Whether builds are publicly visible.
    pub public_builds: bool,
    /// Groups the project is shared with.
    pub shared_with_groups: Vec<SharedGroup>,
    /// Whether the project only enables the merge button if all builds are passing.
    pub only_allow_merge_if_build_succeeds: Option<bool>,
    /// Whether the project only enables the merge button if all discussions are resolved.
    pub only_allow_merge_if_all_discussions_are_resolved: Option<bool>,
    /// Whether access to the project may be requested.
    pub request_access_enabled: bool,
    /// Whether builds are enabled or not.
    pub builds_enabled: bool,
    /// Whether issues are enabled or not.
    pub issues_enabled: bool,
    /// Whether merge requests are enabled or not.
    pub merge_requests_enabled: bool,
    /// Whether snippets are enabled or not.
    pub snippets_enabled: bool,
    /// Whether the project wiki is enabled or not.
    pub wiki_enabled: bool,
    /// Statistics about the project.
    pub statistics: Option<ProjectStatistics>,

    /// If this is present, it is `ProjectWithAccess`, but since it is so similar, just have it be
    /// optional here.
    pub permissions: Option<Permissions>,
}

580
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
/// Statistics about a project.
pub struct ProjectStatistics {
    /// The number of commits in the repository.
    pub commit_count: u64,
    /// The size, in bytes, of the total storage required for the project.
    pub storage_size: u64,
    /// The size, in bytes, of the repository.
    pub repository_size: u64,
    /// The size, in bytes, of uploaded LFS files.
    pub lfs_objects_size: u64,
    /// The size, in bytes, of uploaded build artifacts.
    pub build_artifacts_size: u64,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
/// Access levels for groups and projects.
pub enum AccessLevel {
    /// Anonymous access.
    Anonymous,
    /// Guest access (can see the project).
    Guest,
    /// Reporter access (can open issues).
    Reporter,
    /// Developer access (can push branches, handle issues and merge requests).
    Developer,
    /// Master access (can push to protected branches).
    Master,
    /// Owner access (full rights).
    Owner,
}

impl From<AccessLevel> for u64 {
    fn from(access: AccessLevel) -> Self {
        match access {
            AccessLevel::Anonymous => 0,
            AccessLevel::Guest => 10,
            AccessLevel::Reporter => 20,
            AccessLevel::Developer => 30,
            AccessLevel::Master => 40,
            AccessLevel::Owner => 50,
        }
    }
}

impl From<u64> for AccessLevel {
    fn from(access: u64) -> Self {
        if access >= 50 {
            AccessLevel::Owner
        } else if access >= 40 {
            AccessLevel::Master
        } else if access >= 30 {
            AccessLevel::Developer
        } else if access >= 20 {
            AccessLevel::Reporter
        } else if access >= 10 {
            AccessLevel::Guest
        } else {
            AccessLevel::Anonymous
        }
    }
}

impl Display for AccessLevel {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", Into::<u64>::into(self.clone()))
    }
}

650
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
#[derive(Serialize, Deserialize, Debug, Clone)]
/// A member with extra permissions on a project.
pub struct Member {
    /// The username.
    pub username: String,
    /// The display name.
    pub name: String,
    /// The user's ID.
    pub id: UserId,
    /// The state of the user account.
    pub state: UserState,
    /// The URL of the user's avatar.
    pub avatar_url: String,
    /// The URL of the user's profile page.
    pub web_url: String,
    /// The access level of the user.
    pub access_level: u64,
    /// When the membership expires.
    pub expires_at: Option<DateTime<UTC>>,
}

impl From<Member> for UserBasic {
    fn from(member: Member) -> Self {
        UserBasic {
            username: member.username,
            name: member.name,
            id: member.id,
            state: member.state,
            avatar_url: member.avatar_url,
            web_url: member.web_url,
        }
    }
}

685
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
#[derive(Serialize, Deserialize, Debug, Clone)]
/// A member with extra permissions on a project.
pub struct AccessRequester {
    /// The username.
    pub username: String,
    /// The display name.
    pub name: String,
    /// The user's ID.
    pub id: UserId,
    /// The state of the user account.
    pub state: UserState,
    /// The URL of the user's avatar.
    pub avatar_url: String,
    /// The URL of the user's profile page.
    pub web_url: String,
    /// When the membership request was created.
    pub requested_at: DateTime<UTC>,
}

impl From<AccessRequester> for UserBasic {
    fn from(member: AccessRequester) -> Self {
        UserBasic {
            username: member.username,
            name: member.name,
            id: member.id,
            state: member.state,
            avatar_url: member.avatar_url,
            web_url: member.web_url,
        }
    }
}

718
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
719
720
721
722
723
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
/// Type-safe group ID.
pub struct GroupId(u64);
impl_id!(GroupId);

724
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
#[derive(Serialize, Deserialize, Debug, Clone)]
/// Group information.
pub struct Group {
    /// The ID of the group.
    pub id: GroupId,
    /// The name of the group.
    pub name: String,
    /// The path to the group.
    pub path: String,
    /// The description of the group.
    pub description: Option<String>,
    /// Integral value for the group's visibility.
    pub visibility_level: u64,
    /// Whether LFS is enabled for the group.
    pub lfs_enabled: bool,
    /// The URL to the group avatar.
    pub avatar_url: String,
    /// The URL to the group's profile page.
    pub web_url: String,
    /// Whether membership requests are allowed for the group.
    pub request_access_enabled: bool,
Ben Boeckel's avatar
Ben Boeckel committed
746
747
    pub full_name: String,
    pub full_path: String,
748
749
750
751
    /// Statistics about the group.
    pub statistics: Option<ProjectStatistics>,
}

752
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
753
754
755
756
757
758
759
760
761
762
763
764
765
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
/// Statistics about a group.
pub struct GroupStatistics {
    /// The size, in bytes, of the total storage required for the group.
    pub storage_size: u64,
    /// The size, in bytes, of all repositories in the group.
    pub repository_size: u64,
    /// The size, in bytes, of uploaded LFS files in the group.
    pub lfs_objects_size: u64,
    /// The size, in bytes, of uploaded build artifacts in the group.
    pub build_artifacts_size: u64,
}

766
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
#[derive(Serialize, Deserialize, Debug, Clone)]
/// Group information with a project listing.
pub struct GroupDetail {
    /// The ID of the group.
    pub id: GroupId,
    /// The name of the group.
    pub name: String,
    /// The path to the group.
    pub path: String,
    /// The description of the group.
    pub description: Option<String>,
    /// Integral value for the group's visibility.
    pub visibility_level: u64,
    /// Whether LFS is enabled for the group.
    pub lfs_enabled: bool,
    /// The URL to the group avatar.
    pub avatar_url: String,
    /// The URL to the group's profile page.
    pub web_url: String,
    /// The projects in a group.
    pub projects: Vec<Project>,
    /// Projects the group shares with other groups or users.
    pub shared_projects: Vec<Project>,
    /// Whether membership requests are allowed for the group.
    pub request_access_enabled: bool,
Ben Boeckel's avatar
Ben Boeckel committed
792
793
    pub full_name: String,
    pub full_path: String,
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
    /// Statistics about the group.
    pub statistics: Option<ProjectStatistics>,
}

impl From<GroupDetail> for Group {
    fn from(detail: GroupDetail) -> Self {
        Group {
            id: detail.id,
            name: detail.name,
            path: detail.path,
            description: detail.description,
            visibility_level: detail.visibility_level,
            lfs_enabled: detail.lfs_enabled,
            avatar_url: detail.avatar_url,
            web_url: detail.web_url,
            request_access_enabled: detail.request_access_enabled,
Ben Boeckel's avatar
Ben Boeckel committed
810
811
            full_name: detail.full_name,
            full_path: detail.full_path,
812
813
814
815
816
            statistics: detail.statistics,
        }
    }
}

817
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
#[derive(Serialize, Deserialize, Debug, Clone)]
/// A commit on at the head of a branch.
///
/// NOTE: This is an ad-hoc entity in Gitlab.
pub struct Commit {
    /// The object ID of the commit.
    pub id: ObjectId,
    /// The object IDs of the commit's parents.
    pub parent_ids: Vec<ObjectId>,
    /// The commit message.
    pub message: String,
    /// The commit's author's name.
    pub author_name: String,
    /// The commit's author's email address.
    pub author_email: String,
    /// The commit's authorship date.
    pub authored_date: DateTime<UTC>,
    /// The committer's name.
    pub committer_name: String,
    /// The committer's email address.
    pub committer_email: String,
    /// The commit's commit date.
    pub committed_date: DateTime<UTC>,
}

843
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
#[derive(Serialize, Deserialize, Debug, Clone)]
/// A branch on a repository.
pub struct RepoBranch {
    /// The name of the branch.
    pub name: String,
    /// The commit of the branch.
    pub commit: Option<Commit>,
    /// Whether the branch is merged into the main branch or not.
    pub merged: Option<bool>,
    /// Whether the branch is protected or not.
    pub protected: Option<bool>,
    /// Whether the developers can push directly to the branch or not.
    pub developers_can_push: Option<bool>,
    /// Whether the developers can merge into the branch or not.
    pub developers_can_merge: Option<bool>,
}

861
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
/// The ID of a git object.
pub struct ObjectId(String);

impl ObjectId {
    /// Construct a new `ObjectId`
    pub fn new<O: ToString>(oid: O) -> Self {
        ObjectId(oid.to_string())
    }

    /// The value of the id.
    pub fn value(&self) -> &String {
        &self.0
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// The kinds of objects Gitlab can return.
pub enum ObjectType {
    /// A `tree` object.
    Tree,
    /// A `blob` object.
    Blob,
}
enum_serialize!(ObjectType -> "object type",
    Tree => "tree",
    Blob => "blob",
);

891
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
#[derive(Serialize, Deserialize, Debug, Clone)]
/// An object inside of a repository.
pub struct RepoTreeObject {
    /// The ID of the object.
    pub id: ObjectId,
    /// The name of the object.
    pub name: String,
    #[serde(rename="type")]
    /// The type of the object.
    pub type_: ObjectType,
    /// The path to the object inside of the repository.
    pub path: String,
    /// The mode of the object.
    pub mode: String,
}

908
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
#[derive(Serialize, Deserialize, Debug, Clone)]
/// A commit in a project.
pub struct RepoCommit {
    /// The ID of the commit.
    pub id: ObjectId,
    /// The short ID of the commit.
    pub short_id: ObjectId,
    /// The summary of the commit.
    pub title: String,
    /// The commit author's name.
    pub author_name: String,
    /// The commit author's email address.
    pub author_email: String,
    /// The committer's name.
    pub committer_name: String,
    /// The committer's email address.
    pub committer_email: String,
    pub created_at: DateTime<UTC>,
    /// The full commit message.
    pub message: String,
}

931
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
932
933
934
935
936
937
938
939
940
941
942
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
/// Stats about a commit.
pub struct RepoCommitStats {
    /// The number of lines added by the commit.
    pub additions: u64,
    /// The number of lines deleted by the commit.
    pub deletions: u64,
    /// The number of lines changed by the commit.
    pub total: u64,
}

943
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
#[derive(Serialize, Deserialize, Debug, Clone)]
/// A commit in a project with statistics.
pub struct RepoCommitDetail {
    /// The ID of the commit.
    pub id: ObjectId,
    /// The short ID of the commit.
    pub short_id: ObjectId,
    /// The summary of the commit.
    pub title: String,
    /// The commit author's name.
    pub author_name: String,
    /// The commit author's email address.
    pub author_email: String,
    pub created_at: DateTime<UTC>,
    /// The full commit message.
    pub message: String,
    /// The commit ID of the parents of the commit.
    pub parent_ids: Vec<ObjectId>,
    /// The commit's commit date.
    pub committed_date: DateTime<UTC>,
    /// The commit's authorship date.
    pub authored_date: DateTime<UTC>,
    /// Statistics about the commit.
    pub stats: RepoCommitStats,
968
969
970
    // XXX: Investigate what this is.
    /// This looks to be CI related; ignoring without better docs.
    status: Value,
971
972
}

973
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
974
975
976
977
978
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
/// Type-safe snippet ID.
pub struct SnippetId(u64);
impl_id!(SnippetId);

979
#[cfg_attr(feature="strict", serde(deny_unknown_fields))]
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#[derive(Serialize, Deserialize, Debug, Clone)]
/// A project-specific snippet.
pub struct ProjectSnippet {
    /// The ID of the snippet.
    pub id: SnippetId,
    /// The title of the snippet.
    pub title: String,
    /// The name of the snippet.
    pub file_name: String,
    /// The author of the snippet.
    pub author: UserBasic,
    /// When the snippet was last updated.
    pub updated_at: DateTime<UTC>,
    /// When the snippet was created.
    pub created_at: DateTime<UTC>,
    /// The URL of the snippet.
    pub web_url: String,
}

//class PersonalSnippet < Grape::Entity
//  expose :id, :title, :file_name