Michael Mayo

laying out class structure and making notes

1 -//  
2 -// ASICFRequest.h  
3 -// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest  
4 -//  
5 -// Created by Michael Mayo on 22/12/09.  
6 -// Copyright 2009 All-Seeing Interactive. All rights reserved.  
7 -//  
8 -// A (basic) class for accessing data stored on Rackspace's Cloud Files Service  
9 -// http://www.rackspacecloud.com/cloud_hosting_products/files  
10 -  
11 -#import <Foundation/Foundation.h>  
12 -  
13 -  
14 -@interface ASICFRequest : NSObject {  
15 -  
16 -}  
17 -  
18 -@end  
  1 +//
  2 +// ASICloudFilesCDNRequest.h
  3 +// iPhone
  4 +//
  5 +// Created by Michael Mayo on 1/6/10.
  6 +// Copyright 2010 __MyCompanyName__. All rights reserved.
  7 +//
  8 +
  9 +#import "ASICloudFilesRequest.h"
  10 +
  11 +
  12 +@interface ASICloudFilesCDNRequest : ASICloudFilesRequest {
  13 +
  14 +}
  15 +
  16 +@end
1 // 1 //
2 -// ASICFRequest.m 2 +// ASICloudFilesCDNRequest.m
3 // iPhone 3 // iPhone
4 // 4 //
5 -// Created by Michael Mayo on 12/22/09. 5 +// Created by Michael Mayo on 1/6/10.
6 -// Copyright 2009 __MyCompanyName__. All rights reserved. 6 +// Copyright 2010 __MyCompanyName__. All rights reserved.
7 // 7 //
8 8
9 -#import "ASICFRequest.h" 9 +#import "ASICloudFilesCDNRequest.h"
10 10
11 11
12 -@implementation ASICFRequest 12 +@implementation ASICloudFilesCDNRequest
13 13
14 @end 14 @end
  1 +//
  2 +// ASICloudFilesContainerRequest.h
  3 +// iPhone
  4 +//
  5 +// Created by Michael Mayo on 1/6/10.
  6 +// Copyright 2010 __MyCompanyName__. All rights reserved.
  7 +//
  8 +
  9 +#import "ASICloudFilesRequest.h"
  10 +
  11 +
  12 +@interface ASICloudFilesContainerRequest : ASICloudFilesRequest {
  13 + NSMutableArray *containerNames;
  14 + //NSUInteger containerCount;
  15 + //NSUInteger bytesUsed;
  16 +
  17 + NSUInteger limit;
  18 + NSString *marker; // last item found as the offset
  19 + NSString *format; // json or xml
  20 +
  21 + // Internally used while parsing the response
  22 + NSString *currentContent;
  23 + NSString *currentElement;
  24 + //ASIS3BucketObject *currentObject;
  25 + //NSMutableArray *objects;
  26 +
  27 +}
  28 +
  29 +#pragma mark Constructors
  30 +
  31 +// HEAD /<api version>/<account>
  32 +// HEAD operations against an account are performed to retrieve the number of Containers and the total bytes stored in Cloud Files for the account. This information is returned in two custom headers, X-Account-Container-Count and X-Account-Bytes-Used.
  33 ++ (id)accountInfoRequest;
  34 +
  35 +// GET /<api version>/<account>/<container>
  36 +// Create a request to list all containers
  37 ++ (id)listRequest;
  38 +
  39 +// PUT /<api version>/<account>/<container>
  40 ++ (id)createContainerRequest:(NSString *)containerName;
  41 +
  42 +// DELETE /<api version>/<account>/<container>
  43 ++ (id)deleteContainerRequest:(NSString *)containerName;
  44 +
  45 +
  46 +- (NSUInteger)containerCount;
  47 +- (NSUInteger)bytesUsed;
  48 +
  49 +// ASICloudFilesContainerListRequest
  50 +// GET on account (for containers)
  51 +// limit
  52 +// marker (last item found as the offset)
  53 +// format - 'json' or 'xml'
  54 +
  55 +// create container
  56 +// DELETE to delete
  57 +
  58 +
  59 +@end
  1 +//
  2 +// ASICloudFilesContainerRequest.m
  3 +// iPhone
  4 +//
  5 +// Created by Michael Mayo on 1/6/10.
  6 +// Copyright 2010 __MyCompanyName__. All rights reserved.
  7 +//
  8 +
  9 +#import "ASICloudFilesContainerRequest.h"
  10 +
  11 +
  12 +@implementation ASICloudFilesContainerRequest
  13 +
  14 +//ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:rackspaceCloudAuthURL]];
  15 +//NSMutableDictionary *headers = [[NSMutableDictionary alloc] initWithCapacity:2];
  16 +//[headers setObject:username forKey:@"X-Auth-User"];
  17 +//[headers setObject:apiKey forKey:@"X-Auth-Key"];
  18 +//[request setRequestHeaders:headers];
  19 +//[headers release];
  20 +//return request;
  21 +
  22 +#pragma mark -
  23 +#pragma mark Constructors
  24 +
  25 ++ (id)storageRequestWithMethod:(NSString *)method {
  26 + //ASICloudFilesRequest *request = [ASICloudFilesRequest storageRequest];
  27 + ASICloudFilesContainerRequest *request = [[ASICloudFilesContainerRequest alloc] initWithURL:[NSURL URLWithString:[ASICloudFilesRequest storageURL]]];
  28 + [request setRequestMethod:method];
  29 + NSMutableDictionary *headers = [[NSMutableDictionary alloc] initWithCapacity:1];
  30 + [headers setObject:[ASICloudFilesRequest authToken] forKey:@"X-Auth-Token"];
  31 + [request setRequestHeaders:headers];
  32 + [headers release];
  33 + return request;
  34 +}
  35 +
  36 +// HEAD /<api version>/<account>
  37 +// HEAD operations against an account are performed to retrieve the number of Containers and the total bytes stored in Cloud Files for the account. This information is returned in two custom headers, X-Account-Container-Count and X-Account-Bytes-Used.
  38 ++ (id)accountInfoRequest {
  39 + ASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@"HEAD"];
  40 + return request;
  41 +}
  42 +
  43 +// GET /<api version>/<account>/<container>
  44 +// Create a request to list all containers
  45 ++ (id)listRequest {
  46 + ASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@"GET"];
  47 + return request;
  48 +}
  49 +
  50 +// PUT /<api version>/<account>/<container>
  51 ++ (id)createContainerRequest:(NSString *)containerName {
  52 + ASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@"PUT"];
  53 + return request;
  54 +}
  55 +
  56 +// DELETE /<api version>/<account>/<container>
  57 ++ (id)deleteContainerRequest:(NSString *)containerName {
  58 + ASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest storageRequestWithMethod:@"DELETE"];
  59 + return request;
  60 +}
  61 +
  62 +#pragma mark -
  63 +#pragma mark Response Data
  64 +
  65 +#pragma mark Account Info
  66 +
  67 +- (NSUInteger)containerCount {
  68 + return [[[self responseHeaders] objectForKey:@"X-Account-Container-Count"] intValue];
  69 +}
  70 +
  71 +- (NSUInteger)bytesUsed {
  72 + return [[[self responseHeaders] objectForKey:@"X-Account-Bytes-Used"] intValue];
  73 +}
  74 +
  75 +#pragma mark Container List
  76 +
  77 +- (NSArray *)containers {
  78 + if (containerNames) {
  79 + return containerNames;
  80 + }
  81 + containerNames = [[[NSMutableArray alloc] init] autorelease];
  82 + NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:[self responseData]] autorelease];
  83 + [parser setDelegate:self];
  84 + [parser setShouldProcessNamespaces:NO];
  85 + [parser setShouldReportNamespacePrefixes:NO];
  86 + [parser setShouldResolveExternalEntities:NO];
  87 + [parser parse];
  88 + return containerNames;
  89 +}
  90 +
  91 +#pragma mark -
  92 +#pragma mark XML Parser Delegate
  93 +
  94 +/*
  95 +- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
  96 + [self setCurrentElement:elementName];
  97 +
  98 + if ([elementName isEqualToString:@"Contents"]) {
  99 + [self setCurrentObject:[ASIS3BucketObject objectWithBucket:[self bucket]]];
  100 + }
  101 + [self setCurrentContent:@""];
  102 +}
  103 +
  104 +- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
  105 + if ([elementName isEqualToString:@"Contents"]) {
  106 + [objects addObject:currentObject];
  107 + [self setCurrentObject:nil];
  108 + } else if ([elementName isEqualToString:@"Key"]) {
  109 + [[self currentObject] setKey:[self currentContent]];
  110 + } else if ([elementName isEqualToString:@"LastModified"]) {
  111 + [[self currentObject] setLastModified:[dateFormatter dateFromString:[self currentContent]]];
  112 + } else if ([elementName isEqualToString:@"ETag"]) {
  113 + [[self currentObject] setETag:[self currentContent]];
  114 + } else if ([elementName isEqualToString:@"Size"]) {
  115 + [[self currentObject] setSize:(unsigned long long)[[self currentContent] longLongValue]];
  116 + } else if ([elementName isEqualToString:@"ID"]) {
  117 + [[self currentObject] setOwnerID:[self currentContent]];
  118 + } else if ([elementName isEqualToString:@"DisplayName"]) {
  119 + [[self currentObject] setOwnerName:[self currentContent]];
  120 + }
  121 +}
  122 +
  123 +- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
  124 + [self setCurrentContent:[[self currentContent] stringByAppendingString:string]];
  125 +}
  126 +*/
  127 +
  128 +@end
  1 +//
  2 +// ASICloudFilesObjectRequest.h
  3 +// iPhone
  4 +//
  5 +// Created by Michael Mayo on 1/6/10.
  6 +// Copyright 2010 __MyCompanyName__. All rights reserved.
  7 +//
  8 +
  9 +#import "ASICloudFilesRequest.h"
  10 +
  11 +
  12 +@interface ASICloudFilesObjectRequest : ASICloudFilesRequest {
  13 +
  14 +}
  15 +
  16 +@end
  1 +//
  2 +// ASICloudFilesObjectRequest.m
  3 +// iPhone
  4 +//
  5 +// Created by Michael Mayo on 1/6/10.
  6 +// Copyright 2010 __MyCompanyName__. All rights reserved.
  7 +//
  8 +
  9 +#import "ASICloudFilesObjectRequest.h"
  10 +
  11 +
  12 +@implementation ASICloudFilesObjectRequest
  13 +
  14 +@end
  1 +//
  2 +// ASICloudFilesRequest.h
  3 +// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
  4 +//
  5 +// Created by Michael Mayo on 22/12/09.
  6 +// Copyright 2009 All-Seeing Interactive. All rights reserved.
  7 +//
  8 +// A (basic) class for accessing data stored on Rackspace's Cloud Files Service
  9 +// http://www.rackspacecloud.com/cloud_hosting_products/files
  10 +//
  11 +// Cloud Files Developer Guide:
  12 +// http://docs.rackspacecloud.com/servers/api/cs-devguide-latest.pdf
  13 +
  14 +#import <Foundation/Foundation.h>
  15 +#import "ASIHTTPRequest.h"
  16 +
  17 +
  18 +@interface ASICloudFilesRequest : ASIHTTPRequest {
  19 +
  20 + // ASICloudFilesObjectListRequest
  21 + // GET on container (for objects)
  22 + // limit
  23 + // marker
  24 + // prefix - For a string value X, causes the results to be limited to Object names beginning with the substring X.
  25 + // path - Now issuing a GET request against the Container name coupled with the “path” query parameter of the directory to list can traverse these “directories”. GET /v1/AccountString/backups?path=photos/animals
  26 +
  27 + // PUT /<api version>/<account>/<container>/<object>
  28 + // PUT operations are used to write, or overwrite, an Object's metadata and content.
  29 +
  30 + // POST /<api version>/<account>/<container>/<object>
  31 + // POST operations against an Object name are used to set and overwrite arbitrary key/value metadata. You cannot use the POST operation to change any of the Object's other headers such as Content-Type, ETag, etc. It is not used to upload storage Objects (see PUT).
  32 + // A POST request will delete all existing metadata added with a previous PUT/POST.
  33 +
  34 + // DELETE /<api version>/<account>/<container>/<object>
  35 +
  36 + // GET operations against the X-CDN-Management-Url for an account are performed to retrieve a list of existing CDN-enabled Containers
  37 + // GET /<api version>/<account>
  38 +
  39 + // list containers
  40 + // list objects in a container
  41 + // cdn operations
  42 +
  43 +}
  44 +
  45 ++ (NSString *)storageURL;
  46 ++ (NSString *)authToken;
  47 +
  48 +#pragma mark Rackspace Cloud Authentication
  49 +
  50 ++ (void)authenticate;
  51 +
  52 ++ (NSString *)username;
  53 ++ (void)setUsername:(NSString *)username;
  54 ++ (NSString *)apiKey;
  55 ++ (void)setApiKey:(NSString *)apiKey;
  56 +
  57 +#pragma mark Constructors
  58 +
  59 ++ (id)authenticationRequest;
  60 ++ (id)storageRequest;
  61 ++ (id)cdnRequest;
  62 +
  63 +//+ (id)PUTRequestForFile:(NSString *)filePath withContainer:(NSString *)container path:(NSString *)path;
  64 +
  65 +
  66 +// Create a request to list all objects in a container
  67 +//+ (id)objectListRequestWithContainer:(NSString *)container;
  68 +
  69 +// HEAD /<api version>/<account>/<container>
  70 +// HEAD operations against a storage Container are used to determine the number of Objects, and the total bytes of all Objects stored in the Container.
  71 +// The Object count and utilization are returned in the X- Container-Object-Count and X-Container-Bytes-Used headers respectively.
  72 +
  73 +// HEAD /<api version>/<account>/<container>/<object>
  74 +// No response body is returned. Metadata is returned as HTTP headers. A status code of 204 (No Content) indicates success, status 404 (Not Found) is returned when the Object does not exist.
  75 +
  76 +// CDN URL
  77 +// HEAD /<api version>/<account>/<container>
  78 +// HEAD operations against a CDN-enabled Container are used to determine the CDN attributes of the Container.
  79 +
  80 +// PUT operations against a Container are used to CDN-enable that Container.
  81 +// POST operations against a CDN-enabled Container are used to adjust CDN attributes.
  82 +
  83 +
  84 +
  85 +// Create a request, building an appropriate url
  86 +//+ (id)requestWithContainer:(NSString *)container path:(NSString *)path;
  87 +//
  88 +//// Create a PUT request using the file at filePath as the body
  89 +//+ (id)PUTRequestForFile:(NSString *)filePath withContainer:(NSString *)container path:(NSString *)path;
  90 +//
  91 +//// Create a PUT request using the supplied NSData as the body (set the mime-type manually with setMimeType: if necessary)
  92 +//+ (id)PUTRequestForData:(NSData *)data withContainer:(NSString *)container path:(NSString *)path;
  93 +//
  94 +//// Create a DELETE request for the object at path
  95 +//+ (id)DELETERequestWithContainer:(NSString *)container path:(NSString *)path;
  96 +
  97 +// TODO: CDN toggle containers
  98 +
  99 +@end
  1 +//
  2 +// ASICloudFilesRequest.m
  3 +// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
  4 +//
  5 +// Created by Michael Mayo on 22/12/09.
  6 +// Copyright 2009 All-Seeing Interactive. All rights reserved.
  7 +//
  8 +// A (basic) class for accessing data stored on Rackspace's Cloud Files Service
  9 +// http://www.rackspacecloud.com/cloud_hosting_products/files
  10 +//
  11 +// Cloud Files Developer Guide:
  12 +// http://docs.rackspacecloud.com/servers/api/cs-devguide-latest.pdf
  13 +
  14 +#import "ASICloudFilesRequest.h"
  15 +
  16 +static NSString *username = nil;
  17 +static NSString *apiKey = nil;
  18 +static NSString *authToken = nil;
  19 +static NSString *storageURL = nil;
  20 +static NSString *cdnManagementURL = nil;
  21 +static NSString *rackspaceCloudAuthURL = @"https://auth.api.rackspacecloud.com/v1.0";
  22 +
  23 +@implementation ASICloudFilesRequest
  24 +
  25 ++ (NSString *)storageURL {
  26 + return storageURL;
  27 +}
  28 +
  29 ++ (NSString *)authToken {
  30 + return authToken;
  31 +}
  32 +
  33 +
  34 ++ (id)authenticationRequest {
  35 + ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:rackspaceCloudAuthURL]];
  36 + NSMutableDictionary *headers = [[NSMutableDictionary alloc] initWithCapacity:2];
  37 + [headers setObject:username forKey:@"X-Auth-User"];
  38 + [headers setObject:apiKey forKey:@"X-Auth-Key"];
  39 + [request setRequestHeaders:headers];
  40 + [headers release];
  41 + return request;
  42 +}
  43 +
  44 ++ (id)storageRequest {
  45 + ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:storageURL]];
  46 + return request;
  47 +}
  48 +
  49 ++ (id)cdnRequest {
  50 + ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:cdnManagementURL]];
  51 + return request;
  52 +}
  53 +
  54 ++ (void)authenticate {
  55 + ASIHTTPRequest *request = [ASICloudFilesRequest authenticationRequest];
  56 +
  57 + [request start];
  58 +
  59 + if (![request error]) {
  60 + NSDictionary *responseHeaders = [request responseHeaders];
  61 + authToken = [responseHeaders objectForKey:@"X-Auth-Token"];
  62 + storageURL = [responseHeaders objectForKey:@"X-Storage-Url"];
  63 + cdnManagementURL = [responseHeaders objectForKey:@"X-Cdn-Management-Url"];
  64 + } else {
  65 + NSLog(@"%@",[[request error] localizedDescription]);
  66 + }
  67 +}
  68 +
  69 ++ (NSString *)username {
  70 + return username;
  71 +}
  72 +
  73 ++ (void)setUsername:(NSString *)newUsername {
  74 + [username release];
  75 + username = [newUsername retain];
  76 +}
  77 +
  78 ++ (NSString *)apiKey {
  79 + return apiKey;
  80 +}
  81 +
  82 ++ (void)setApiKey:(NSString *)newApiKey {
  83 + [apiKey release];
  84 + apiKey = [newApiKey retain];
  85 +}
  86 +
  87 +
  88 +
  89 +@end
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 #import "ASIInputStream.h" 21 #import "ASIInputStream.h"
22 22
23 // Automatically set on build 23 // Automatically set on build
24 -NSString *ASIHTTPRequestVersion = @"v1.2-24 2009-12-18"; 24 +NSString *ASIHTTPRequestVersion = @"v1.2-26 2010-01-07";
25 25
26 // We use our own custom run loop mode as CoreAnimation seems to want to hijack our threads otherwise 26 // We use our own custom run loop mode as CoreAnimation seems to want to hijack our threads otherwise
27 static CFStringRef ASIHTTPRequestRunMode = CFSTR("ASIHTTPRequest"); 27 static CFStringRef ASIHTTPRequestRunMode = CFSTR("ASIHTTPRequest");
  1 +//
  2 +// ASICloudFilesRequestTests.h
  3 +// iPhone
  4 +//
  5 +// Created by Michael Mayo on 1/6/10.
  6 +// Copyright 2010 __MyCompanyName__. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +#import "ASITestCase.h"
  11 +
  12 +@class ASINetworkQueue;
  13 +
  14 +@interface ASICloudFilesRequestTests : NSObject {
  15 + ASINetworkQueue *networkQueue;
  16 +}
  17 +
  18 +@end
  1 +//
  2 +// ASICloudFilesRequestTests.m
  3 +// iPhone
  4 +//
  5 +// Created by Michael Mayo on 1/6/10.
  6 +// Copyright 2010 __MyCompanyName__. All rights reserved.
  7 +//
  8 +
  9 +#import "ASICloudFilesRequestTests.h"
  10 +
  11 +
  12 +@implementation ASICloudFilesRequestTests
  13 +
  14 +@end
@@ -9,6 +9,10 @@ @@ -9,6 +9,10 @@
9 #import "iPhoneSampleAppDelegate.h" 9 #import "iPhoneSampleAppDelegate.h"
10 #import "ASIHTTPRequest.h" 10 #import "ASIHTTPRequest.h"
11 #import "Reachability.h" 11 #import "Reachability.h"
  12 +#import "ASICloudFilesRequest.h"
  13 +#import "ASICloudFilesContainerRequest.h"
  14 +#import "ASICloudFilesObjectRequest.h"
  15 +#import "ASICloudFilesCDNRequest.h"
12 16
13 @implementation iPhoneSampleAppDelegate 17 @implementation iPhoneSampleAppDelegate
14 18
@@ -26,6 +30,33 @@ @@ -26,6 +30,33 @@
26 30
27 - (void)applicationDidFinishLaunching:(UIApplication *)application { 31 - (void)applicationDidFinishLaunching:(UIApplication *)application {
28 32
  33 + NSLog(@"time to test Cloud Files!");
  34 +
  35 + [ASICloudFilesRequest setUsername:@"greenisus"];
  36 + [ASICloudFilesRequest setApiKey:@"1c331a7a4a6eb58ca6072afe81e812d0"];
  37 + [ASICloudFilesRequest authenticate];
  38 +
  39 + NSLog(@"Storage URL: %@", [ASICloudFilesRequest storageURL]);
  40 +
  41 + NSLog(@"account info:");
  42 +
  43 + ASICloudFilesContainerRequest *accountInfoRequest = [ASICloudFilesContainerRequest accountInfoRequest];
  44 + [accountInfoRequest start];
  45 +
  46 + NSLog(@"Response status code: %i", [accountInfoRequest responseStatusCode]);
  47 + NSLog(@"Response status message: %@", [accountInfoRequest responseStatusMessage]);
  48 + NSLog(@"Container count: %i", [accountInfoRequest containerCount]);
  49 + NSLog(@"Bytes used: %i", [accountInfoRequest bytesUsed]);
  50 +
  51 + NSLog(@"All headers:");
  52 + NSDictionary *headers = [accountInfoRequest responseHeaders];
  53 + NSArray *keys = [headers allKeys];
  54 + for (int i = 0; i < [keys count]; i++) {
  55 + NSString *key = [keys objectAtIndex:i];
  56 + NSLog(@"%@: %@", key, [headers objectForKey:key]);
  57 + }
  58 +
  59 +
29 // Add the tab bar controller's current view as a subview of the window 60 // Add the tab bar controller's current view as a subview of the window
30 [window addSubview:[tabBarController view]]; 61 [window addSubview:[tabBarController view]];
31 [[tabBarController view] setFrame:CGRectMake(0,47,320,433)]; 62 [[tabBarController view] setFrame:CGRectMake(0,47,320,433)];
This diff was suppressed by a .gitattributes entry.
1 #!/bin/sh 1 #!/bin/sh
2 -versionString=`/opt/local/bin/git describe --tags` 2 +versionString=`/usr/local/bin/git describe --tags`
3 version="`echo $versionString | sed -E 's/(v([0-9]+)\.([0-9]+))(.*)/\1/g'`" 3 version="`echo $versionString | sed -E 's/(v([0-9]+)\.([0-9]+))(.*)/\1/g'`"
4 commitNum="`echo $versionString | sed -E 's/(v([0-9]+)\.([0-9]+))\-([0-9]*)(.*)/\4/g'`" 4 commitNum="`echo $versionString | sed -E 's/(v([0-9]+)\.([0-9]+))\-([0-9]*)(.*)/\4/g'`"
5 date=`date "+%Y-%m-%d"` 5 date=`date "+%Y-%m-%d"`