//
// Project.m
// Coding_iOS
//
// Created by Ease on 15/4/23.
// Copyright (c) 2015 Coding. All rights reserved.
//
#import "Project.h"
#import "Login.h"
#import "NProjectViewController.h"
#import "EALocalCodeListViewController.h"
@implementation Project
- (BOOL)hasEverHandledBoard{
NSNumber *hasEverHandledBoard = [[NSUserDefaults standardUserDefaults] objectForKey:self.p_hasEverHandledBoardKey];
return hasEverHandledBoard? hasEverHandledBoard.boolValue : NO;
}
- (void)setHasEverHandledBoard:(BOOL)hasEverHandledBoard{
[[NSUserDefaults standardUserDefaults] setObject:@(hasEverHandledBoard) forKey:self.p_hasEverHandledBoardKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (NSString *)p_hasEverHandledBoardKey{
return [NSString stringWithFormat:@"%@/%@/hasEverHandledBoardKey", self.owner_user_name, self.name];
}
- (instancetype)init
{
self = [super init];
if (self) {
_isStaring = _isWatching = _isLoadingMember = _isLoadingDetail = NO;
_recommended = [NSNumber numberWithInteger:0];
}
return self;
}
- (void)setBackend_project_path:(NSString *)backend_project_path{
if ([backend_project_path hasPrefix:@"/team/"]) {
backend_project_path = [backend_project_path stringByReplacingOccurrencesOfString:@"/team/" withString:@"/user/"];
}
_backend_project_path = backend_project_path;
}
-(id)copyWithZone:(NSZone*)zone {
Project *person = [[[self class] allocWithZone:zone] init];
person.icon = [_icon copy];
person.name = [_name copy];
person.owner_user_name = [_owner_user_name copy];
person.backend_project_path = [_backend_project_path copy];
person.full_name = [_full_name copy];
person.description_mine = [_description_mine copy];
person.path = [_path copy];
person.current_user_role = [_current_user_role copy];
person.id = [_id copy];
person.owner_id = [_owner_id copy];
person.is_public = [_is_public copy];
person.un_read_activities_count = [_un_read_activities_count copy];
person.done = [_done copy];
person.processing = [_processing copy];
person.star_count = [_star_count copy];
person.stared = [_stared copy];
person.watch_count = [_watch_count copy];
person.watched = [_watched copy];
person.fork_count = [_fork_count copy];
person.recommended = [_recommended copy];
person.current_user_role_id = [_current_user_role_id copy];
person.isStaring = _isStaring;
person.isWatching = _isWatching;
person.isLoadingMember = _isLoadingMember;
person.isLoadingMember = _isLoadingMember;
person.created_at = [_created_at copy];
person.updated_at = [_updated_at copy];
person.project_path=[_project_path copy];
person.owner=[_owner copy];
return person;
}
- (void)setFull_name:(NSString *)full_name{
_full_name = full_name;
NSArray *components = [_full_name componentsSeparatedByString:@"/"];
if (components.count == 2) {
if (!_owner_user_name) {
_owner_user_name = components[0];
}
if (_name) {
_name = components[1];
}
}
}
+(Project *)project_All{
Project *pro = [[Project alloc] init];
pro.id = [NSNumber numberWithInteger:-1];
return pro;
}
+ (Project *)project_FeedBack{
Project *pro = [[Project alloc] init];
pro.id = [NSNumber numberWithInteger:38894];//iOS
pro.is_public = [NSNumber numberWithBool:YES];
return pro;
}
-(NSString *)toProjectPath{
return @"api/project";
}
-(NSDictionary *)toCreateParams{
NSString *type;
if ([self.is_public isEqual:@YES]) {
type = @"1";
}else{
type = @"2";
}
return @{@"name":self.name,
@"description":self.description_mine,
@"type":type,
@"gitEnabled":@"true",
@"gitReadmeEnabled": _gitReadmeEnabled.boolValue? @"true": @"false",
@"gitIgnore":@"no",
@"gitLicense":@"no",
// @"importFrom":@"no",
@"vcsType":@"git"};
}
-(NSString *)toUpdatePath{
return [self toProjectPath];
}
-(NSDictionary *)toUpdateParams{
return @{@"name":self.name,
@"description":self.description_mine,
@"id":self.id
// @"default_branch":[NSNull null]
};
}
-(NSString *)toUpdateIconPath{
return [NSString stringWithFormat:@"api/project/%@/project_icon",self.id];
}
-(NSString *)toDeletePath{
return [NSString stringWithFormat:@"api/user/%@/project/%@",self.owner_user_name, self.name];
}
- (NSString *)toArchivePath{
return [NSString stringWithFormat:@"api/project/%@/archive", self.id];
}
- (NSString *)toMembersPath{
if ([_id isKindOfClass:[NSNumber class]]) {
return [NSString stringWithFormat:@"api/project/%d/members", self.id.intValue];
}else{
return [NSString stringWithFormat:@"api/user/%@/project/%@/members", _owner_user_name, _name];
}
}
- (NSDictionary *)toMembersParams{
return @{@"page" : [NSNumber numberWithInteger:1],
@"pageSize" : [NSNumber numberWithInteger:500]};
}
- (NSString *)toUpdateVisitPath{
if (self.owner_user_name.length > 0 && self.name.length > 0) {
return [NSString stringWithFormat:@"api/user/%@/project/%@/update_visit", self.owner_user_name, self.name];
}else{
return [NSString stringWithFormat:@"api/project/%d/update_visit", self.id.intValue];
}
}
- (NSString *)toDetailPath{
return [NSString stringWithFormat:@"api/user/%@/project/%@", self.owner_user_name, self.name];
}
- (NSString *)localMembersPath{
return [NSString stringWithFormat:@"%@_MembersPath", self.id.stringValue];
}
- (NSString *)toBranchOrTagPath:(NSString *)path{
return [NSString stringWithFormat:@"api/user/%@/project/%@/git/%@", self.owner_user_name, self.name, path];
}
//- (NSString *)description_mine{
// if (_description_mine && _description_mine.length > 0) {
// return _description_mine;
// }else{
// return @"";
// }
//}
- (NSURL *)remoteURL{
NSURL *remoteURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://git.coding.net/%@/%@.git", self.owner_user_name, self.name]];
return remoteURL;
}
- (NSURL *)localURL{
NSFileManager* fileManager = [NSFileManager defaultManager];
NSURL *appDocsDir = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].lastObject;
NSURL *localURL = [NSURL URLWithString:[NSString stringWithFormat:@"repositories/%@/%@", self.owner_user_name, self.name] relativeToURL:appDocsDir];
return localURL;
}
- (BOOL)isLocalRepoExist{
NSFileManager* fileManager = [NSFileManager defaultManager];
return [fileManager fileExistsAtPath:self.localURL.path];
}
- (BOOL)deleteLocalRepo{
NSFileManager* fileManager = [NSFileManager defaultManager];
return [fileManager removeItemAtURL:self.localURL error:nil];
}
- (GTRepository *)localRepo{
NSError *error = nil;
GTRepository *repo = [GTRepository repositoryWithURL:self.localURL error:&error];
return repo;
}
- (void)gitCloneBlock:(void(^)(GTRepository *repo, NSError *error))handleBlock progressBlock:(void (^)(const git_transfer_progress *progress, BOOL *stop))progressBlock{
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSError *error = nil;
GTCheckoutOptions *checkoutOptions = [GTCheckoutOptions checkoutOptionsWithStrategy:GTCheckoutStrategyForce];
NSMutableDictionary *cloneOptions = @{GTRepositoryCloneOptionsCheckoutOptions: checkoutOptions}.mutableCopy;
if (weakSelf.is_public && !weakSelf.is_public.boolValue) {//
cloneOptions[GTRepositoryCloneOptionsCredentialProvider] = [weakSelf.class p_credentialProvider];
}
GTRepository *repo = [GTRepository cloneFromURL:weakSelf.remoteURL toWorkingDirectory:weakSelf.localURL options:cloneOptions error:&error transferProgressBlock:progressBlock];
dispatch_async(dispatch_get_main_queue(), ^{
if (handleBlock) {
handleBlock(repo, error);
}
});
});
}
- (void)gitPullBlock:(void(^)(BOOL result, NSString *tipStr))handleBlock progressBlock:(void (^)(const git_transfer_progress *progress, BOOL *stop))progressBlock{
if (!self.isLocalRepoExist) {
handleBlock(NO, @"");
}else{
GTRepository *repo = [GTRepository repositoryWithURL:self.localURL error:nil];
if (!repo) {
handleBlock(NO, @"");
}else{
GTConfiguration *configuration = [repo configurationWithError:nil];
GTRemote *remote = configuration.remotes.firstObject;
if (!remote) {
handleBlock(NO, @"");
}else{
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSError *error = nil;
NSArray *branchList = [repo localBranchesWithError:&error];
if (branchList.count > 0) {
GTBranch *curBranch = branchList.firstObject;
NSMutableDictionary *options = @{GTRepositoryRemoteOptionsDownloadTags: @(GTRemoteDownloadTagsAuto)}.mutableCopy;
if (weakSelf.is_public && !weakSelf.is_public.boolValue) {//
options[GTRepositoryRemoteOptionsCredentialProvider] = [weakSelf.class p_credentialProvider];
}
NSError *error = nil;
BOOL result = [repo pullBranch:curBranch fromRemote:remote withOptions:options error:&error progress:progressBlock];
dispatch_async(dispatch_get_main_queue(), ^{
if (handleBlock) {
handleBlock(result, error.localizedDescription);
}
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
if (handleBlock) {
handleBlock(NO, @" clone ");
}
});
}
});
}
}
}
}
+ (GTCredentialProvider *)p_credentialProvider{
__block NSInteger credTimes = 0;
GTCredentialProvider *provider = [GTCredentialProvider providerWithBlock:^GTCredential *(GTCredentialType type, NSString *URL, NSString *credUserName) {
GTCredential *cred = nil;
if (type & GTCredentialTypeUserPassPlaintext) {
if (credTimes < 10) {//
NSString *userName = [Login curLoginUser].global_key ?: @"";
NSString *password = [Login curPassword] ?: @"";
cred = [GTCredential credentialWithUserName:userName password:password error:nil];
}else{
[self p_handleCredentialFailure];
}
}
credTimes++;
return cred;
}];
return provider;
}
+ (void)p_handleCredentialFailure{
UIAlertController *alertCtrl = [UIAlertController alertControllerWithTitle:@"" message:@"HTTP/S " preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelA = [UIAlertAction actionWithTitle:@"" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *confirmA = [UIAlertAction actionWithTitle:@"" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
NSString *textStr = alertCtrl.textFields[0].text;
[Login setPassword:textStr];
//
UIViewController *vc = [BaseViewController presentingVC];
if ([vc isKindOfClass:[NProjectViewController class]]) {
[(NProjectViewController *)vc cloneRepo];
}else if ([vc isKindOfClass:[EALocalCodeListViewController class]]){
[(EALocalCodeListViewController *)vc pullRepo];
}
}];
[alertCtrl addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.placeholder = @"";
textField.secureTextEntry = YES;
}];
[alertCtrl addAction:cancelA];
[alertCtrl addAction:confirmA];
[[BaseViewController presentingVC] presentViewController:alertCtrl animated:YES completion:nil];
}
@end