...

Source file src/github.com/Azure/azure-sdk-for-go/storage/directory.go

Documentation: github.com/Azure/azure-sdk-for-go/storage

     1  package storage
     2  
     3  // Copyright (c) Microsoft Corporation. All rights reserved.
     4  // Licensed under the MIT License. See License.txt in the project root for license information.
     5  
     6  import (
     7  	"encoding/xml"
     8  	"net/http"
     9  	"net/url"
    10  	"sync"
    11  )
    12  
    13  // Directory represents a directory on a share.
    14  type Directory struct {
    15  	fsc        *FileServiceClient
    16  	Metadata   map[string]string
    17  	Name       string `xml:"Name"`
    18  	parent     *Directory
    19  	Properties DirectoryProperties
    20  	share      *Share
    21  }
    22  
    23  // DirectoryProperties contains various properties of a directory.
    24  type DirectoryProperties struct {
    25  	LastModified string `xml:"Last-Modified"`
    26  	Etag         string `xml:"Etag"`
    27  }
    28  
    29  // ListDirsAndFilesParameters defines the set of customizable parameters to
    30  // make a List Files and Directories call.
    31  //
    32  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/List-Directories-and-Files
    33  type ListDirsAndFilesParameters struct {
    34  	Prefix     string
    35  	Marker     string
    36  	MaxResults uint
    37  	Timeout    uint
    38  }
    39  
    40  // DirsAndFilesListResponse contains the response fields from
    41  // a List Files and Directories call.
    42  //
    43  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/List-Directories-and-Files
    44  type DirsAndFilesListResponse struct {
    45  	XMLName     xml.Name    `xml:"EnumerationResults"`
    46  	Xmlns       string      `xml:"xmlns,attr"`
    47  	Marker      string      `xml:"Marker"`
    48  	MaxResults  int64       `xml:"MaxResults"`
    49  	Directories []Directory `xml:"Entries>Directory"`
    50  	Files       []File      `xml:"Entries>File"`
    51  	NextMarker  string      `xml:"NextMarker"`
    52  }
    53  
    54  // builds the complete directory path for this directory object.
    55  func (d *Directory) buildPath() string {
    56  	path := ""
    57  	current := d
    58  	for current.Name != "" {
    59  		path = "/" + current.Name + path
    60  		current = current.parent
    61  	}
    62  	return d.share.buildPath() + path
    63  }
    64  
    65  // Create this directory in the associated share.
    66  // If a directory with the same name already exists, the operation fails.
    67  //
    68  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Create-Directory
    69  func (d *Directory) Create(options *FileRequestOptions) error {
    70  	// if this is the root directory exit early
    71  	if d.parent == nil {
    72  		return nil
    73  	}
    74  
    75  	params := prepareOptions(options)
    76  	headers, err := d.fsc.createResource(d.buildPath(), resourceDirectory, params, mergeMDIntoExtraHeaders(d.Metadata, nil), []int{http.StatusCreated})
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	d.updateEtagAndLastModified(headers)
    82  	return nil
    83  }
    84  
    85  // CreateIfNotExists creates this directory under the associated share if the
    86  // directory does not exist. Returns true if the directory is newly created or
    87  // false if the directory already exists.
    88  //
    89  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Create-Directory
    90  func (d *Directory) CreateIfNotExists(options *FileRequestOptions) (bool, error) {
    91  	// if this is the root directory exit early
    92  	if d.parent == nil {
    93  		return false, nil
    94  	}
    95  
    96  	params := prepareOptions(options)
    97  	resp, err := d.fsc.createResourceNoClose(d.buildPath(), resourceDirectory, params, nil)
    98  	if resp != nil {
    99  		defer drainRespBody(resp)
   100  		if resp.StatusCode == http.StatusCreated || resp.StatusCode == http.StatusConflict {
   101  			if resp.StatusCode == http.StatusCreated {
   102  				d.updateEtagAndLastModified(resp.Header)
   103  				return true, nil
   104  			}
   105  
   106  			return false, d.FetchAttributes(nil)
   107  		}
   108  	}
   109  
   110  	return false, err
   111  }
   112  
   113  // Delete removes this directory.  It must be empty in order to be deleted.
   114  // If the directory does not exist the operation fails.
   115  //
   116  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Delete-Directory
   117  func (d *Directory) Delete(options *FileRequestOptions) error {
   118  	return d.fsc.deleteResource(d.buildPath(), resourceDirectory, options)
   119  }
   120  
   121  // DeleteIfExists removes this directory if it exists.
   122  //
   123  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Delete-Directory
   124  func (d *Directory) DeleteIfExists(options *FileRequestOptions) (bool, error) {
   125  	resp, err := d.fsc.deleteResourceNoClose(d.buildPath(), resourceDirectory, options)
   126  	if resp != nil {
   127  		defer drainRespBody(resp)
   128  		if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
   129  			return resp.StatusCode == http.StatusAccepted, nil
   130  		}
   131  	}
   132  	return false, err
   133  }
   134  
   135  // Exists returns true if this directory exists.
   136  func (d *Directory) Exists() (bool, error) {
   137  	exists, headers, err := d.fsc.resourceExists(d.buildPath(), resourceDirectory)
   138  	if exists {
   139  		d.updateEtagAndLastModified(headers)
   140  	}
   141  	return exists, err
   142  }
   143  
   144  // FetchAttributes retrieves metadata for this directory.
   145  //  See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/get-directory-properties
   146  func (d *Directory) FetchAttributes(options *FileRequestOptions) error {
   147  	params := prepareOptions(options)
   148  	headers, err := d.fsc.getResourceHeaders(d.buildPath(), compNone, resourceDirectory, params, http.MethodHead)
   149  	if err != nil {
   150  		return err
   151  	}
   152  
   153  	d.updateEtagAndLastModified(headers)
   154  	d.Metadata = getMetadataFromHeaders(headers)
   155  
   156  	return nil
   157  }
   158  
   159  // GetDirectoryReference returns a child Directory object for this directory.
   160  func (d *Directory) GetDirectoryReference(name string) *Directory {
   161  	return &Directory{
   162  		fsc:    d.fsc,
   163  		Name:   name,
   164  		parent: d,
   165  		share:  d.share,
   166  	}
   167  }
   168  
   169  // GetFileReference returns a child File object for this directory.
   170  func (d *Directory) GetFileReference(name string) *File {
   171  	return &File{
   172  		fsc:    d.fsc,
   173  		Name:   name,
   174  		parent: d,
   175  		share:  d.share,
   176  		mutex:  &sync.Mutex{},
   177  	}
   178  }
   179  
   180  // ListDirsAndFiles returns a list of files and directories under this directory.
   181  // It also contains a pagination token and other response details.
   182  //
   183  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/List-Directories-and-Files
   184  func (d *Directory) ListDirsAndFiles(params ListDirsAndFilesParameters) (*DirsAndFilesListResponse, error) {
   185  	q := mergeParams(params.getParameters(), getURLInitValues(compList, resourceDirectory))
   186  
   187  	resp, err := d.fsc.listContent(d.buildPath(), q, nil)
   188  	if err != nil {
   189  		return nil, err
   190  	}
   191  
   192  	defer resp.Body.Close()
   193  	var out DirsAndFilesListResponse
   194  	err = xmlUnmarshal(resp.Body, &out)
   195  	return &out, err
   196  }
   197  
   198  // SetMetadata replaces the metadata for this directory.
   199  //
   200  // Some keys may be converted to Camel-Case before sending. All keys
   201  // are returned in lower case by GetDirectoryMetadata. HTTP header names
   202  // are case-insensitive so case munging should not matter to other
   203  // applications either.
   204  //
   205  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Set-Directory-Metadata
   206  func (d *Directory) SetMetadata(options *FileRequestOptions) error {
   207  	headers, err := d.fsc.setResourceHeaders(d.buildPath(), compMetadata, resourceDirectory, mergeMDIntoExtraHeaders(d.Metadata, nil), options)
   208  	if err != nil {
   209  		return err
   210  	}
   211  
   212  	d.updateEtagAndLastModified(headers)
   213  	return nil
   214  }
   215  
   216  // updates Etag and last modified date
   217  func (d *Directory) updateEtagAndLastModified(headers http.Header) {
   218  	d.Properties.Etag = headers.Get("Etag")
   219  	d.Properties.LastModified = headers.Get("Last-Modified")
   220  }
   221  
   222  // URL gets the canonical URL to this directory.
   223  // This method does not create a publicly accessible URL if the directory
   224  // is private and this method does not check if the directory exists.
   225  func (d *Directory) URL() string {
   226  	return d.fsc.client.getEndpoint(fileServiceName, d.buildPath(), url.Values{})
   227  }
   228  

View as plain text