批量移动文件

@param $srcBucket
@param $keys
@param $destBucket
@param string $prefix
@param string $suffix
@param bool $force
@return array
489458
public function batchMove($srcBucket, $keys, $destBucket, $prefix='', $suffix='', $force=true){
        $keyPairs = array();
        foreach ($keys as $key) {
            $keyPairs[$key] = $prefix."_".$key."_".$suffix;
        }
        $ops = $this->bucketManager->buildBatchMove($srcBucket, $keyPairs, $destBucket, $force);
        list($ret, $err) = $this->bucketManager->batch($ops);
        if($err){
            return $this->error($err->message(), ['errorCode'=>$err->code()]);
        }
        return $this->success('操作成功', $ret);
    }
176448
private static function appendIfPresent($src, $key, $dest)
    {
        if (!empty($src[$key])) {
            return array_merge($dest, $src[$key]);
        } else {
            return $dest;
        }
    }
1247034
public function listFiles($limit = '', $prefix = '', $marker = '', $bucket = '')
    {
        $bucket = $bucket ? $bucket : $this->bucket;
        $params = array_filter(compact('bucket', 'limit', 'prefix', 'marker'));
        $url = $this->rsf_host . '/list?' . http_build_query($params);
        return $this->fileHandle($url);
    }
620657
private function copy(array $sources, $dest, $minify)
    {
        // create destination path if not exists

        $ext = pathinfo($dest, PATHINFO_EXTENSION);
        $dir = !empty($ext) ? dirname($dest) : $dest;
        if (!file_exists($dir)) {
            if (!make_dir($dir, 0775)) {
                throw new RuntimeException('Unable to create directory ' . $dir); // @codeCoverageIgnore
            }
        }

        // list all source files into a flat array

        $files = [];
        foreach ($sources as $source) {
            if (is_dir($source)) {
                if ($ext == 'js') {
                    $filter = ['js'];
                }
                else if ($ext == 'css') {
                    $filter = ['css', 'less', 'scss'];
                }
                else {
                    $filter = null;
                }
                list_files($files, $source, $filter);
            }
            else {
                $files[] = $source;
            }
        }

        // copy all files to the destination

        if (file_exists($dest) && !is_dir($dest)) {
            unlink($dest);
        } // @codeCoverageIgnore

        foreach ($files as $file) {
            // get content
            $content = file_get_contents($file);

            // compile
            $srcExt = pathinfo($file, PATHINFO_EXTENSION);
            switch ($srcExt) {
                case 'less':
//                    $content = (new LessCompiler)->compile($content);
                    $content = (new LessCompiler)->parse($content)->getCss();
                    break;
                case 'scss':
                    $content = (new SCSSCompiler)->compile($content);
                    break;
            }

            // minimize
            if ($minify) {
                switch ($srcExt) {
                    case 'js':
                        $content = JSMin::minify($content);
                        break;
                    case 'css':
                    case 'less':
                    case 'scss':
                        $content = CssMin::minify($content);
                        break;
                }
            }

            // save content
            if (is_dir($dest)) {
                $success = file_put_contents($dest . DIRECTORY_SEPARATOR . basename($file), $content, LOCK_EX);
                //@chmod($dest . DIRECTORY_SEPARATOR . basename($file), 0664);
            }
            else {
                // concatenate the files to a single file
                if (file_exists($dest)) {
                    $success = file_put_contents($dest, PHP_EOL . $content, FILE_APPEND | LOCK_EX);
                }
                else {
                    $success = file_put_contents($dest, $content, LOCK_EX);
                    //@chmod($dest, 0664);
                }
            }
            if ($success === false) {
                throw new RuntimeException(sprintf('Asset Manager was not able to copy "%s" to "%s"', $file, $dest)); // @codeCoverageIgnore
            }
        }
    }
557814
protected function doJoins($source, $joins, &$dest, $from, $contextAlias, $buildImpactIndex=true)
    {
        // expand sequences before doing any joins...
        $this->expandSequence($joins,$source);

        foreach ($joins as $predicate=>$ruleset) {
            if ($predicate=='followSequence') {
                continue;
            }

            if (isset($source[$predicate]))
            {
                // todo: perhaps we can get better performance by detecting whether or not
                // the uri to join on is already in the impact index, and if so not attempting
                // to join on it. However, we need to think about different combinations of
                // nested joins in different points of the view spec and see if this would
                // complicate things. Needs a unit test or two.
                $joinUris = [];
                if (isset($source[$predicate][VALUE_URI]))
                {
                    // single value for join
                    $joinUris[] = array(_ID_RESOURCE=>$source[$predicate][VALUE_URI],_ID_CONTEXT=>$contextAlias);
                }
                else
                {
                    // multiple values for join
                    $joinsPushed = 0;
                    foreach ($source[$predicate] as $v)
                    {
                        if (isset($ruleset['maxJoins']) && !$joinsPushed<$ruleset['maxJoins'])
                        {
                            break; // maxJoins reached
                        }
                        $joinUris[] = array(_ID_RESOURCE=>$v[VALUE_URI],_ID_CONTEXT=>$contextAlias);
                        $joinsPushed++;
                    }
                }

                $recursiveJoins = [];
                $collection = (
                isset($ruleset['from'])
                    ? $this->config->getCollectionForCBD($this->storeName, $ruleset['from'])
                    : $this->config->getCollectionForCBD($this->storeName, $from)
                );

                $cursor = $collection->find(array('_id'=>array('$in'=>$joinUris)), array(
                    'maxTimeMS' => $this->getConfigInstance()->getMongoCursorTimeout()
                ));

                $this->addIdToImpactIndex($joinUris, $dest, $buildImpactIndex);
                foreach($cursor as $linkMatch) {
                    // if there is a condition, check it...
                    if (isset($ruleset['condition']))
                    {
                        $ruleset['condition']['._id'] = $linkMatch['_id'];
                    }
                    if (!(isset($ruleset['condition']) && $collection->count($ruleset['condition'])==0))
                    {
                        // make sure any sequences are expanded before extracting properties
                        if (isset($ruleset['joins'])) $this->expandSequence($ruleset['joins'],$linkMatch);
                        if (isset($ruleset['filter']))
                        {
                            foreach($ruleset['filter'] as $filterPredicate => $filter)
                            {
                                foreach($filter as $filterType => $filterMatch)
                                {
                                    if (isset($linkMatch[$filterPredicate]))
                                    {
                                        foreach($linkMatch[$filterPredicate] as $linkMatchType => $linkMatchValues)
                                        {
                                            if (is_array($linkMatchValues) == false)
                                            {
                                                $linkMatchValues = array($linkMatchType => $linkMatchValues);
                                            }
                                            foreach($linkMatchValues as $linkMatchType => $linkMatchValue)
                                            {
                                                if ($this->matchesFilter($linkMatchType, $linkMatchValue, $filterType, $filterMatch))
                                                {
                                                    $dest[_GRAPHS][] = $this->extractProperties($linkMatch,$ruleset,$from);
                                                }
                                            }

                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            $dest[_GRAPHS][] = $this->extractProperties($linkMatch,$ruleset,$from);
                        }

                        if (isset($ruleset['joins']))
                        {
                            // recursive joins must be done after this cursor has completed, otherwise things get messy
                            $recursiveJoins[] = array('data'=>$linkMatch, 'ruleset'=>$ruleset['joins']);
                        }
                    }
                }
                if (count($recursiveJoins)>0)
                {
                    foreach ($recursiveJoins as $r)
                    {
                        $this->doJoins($r['data'],$r['ruleset'],$dest,$from,$contextAlias,$buildImpactIndex);
                    }
                }
            }
        }
        return;
    }
373752
public Response copy(String fromBucket, String fromFileKey, String toBucket, String toFileKey, boolean force)
            throws QiniuException {
        String from = encodedEntry(fromBucket, fromFileKey);
        String to = encodedEntry(toBucket, toFileKey);
        String path = String.format("/copy/%s/%s/force/%s", from, to, force);
        return rsPost(fromBucket, path, null);
    }
97978
public function getCacheFile( $key = null, $extension='.cache' )
    {
        $cacheDir = $this->configs['cache_dir'];
        /**
         * 1. 如果有传入了缓存key,则默认为公共缓存，缓存文件全部放入公共缓存中
         * 2. 如果key=null,则认为是模块的特殊缓存，按照模块将缓存分类
         */
        if ( $key ) {
            $dir = getHashCode($key) % self::$_FILE_OPACITY;
            $cacheDir .= "common/{$dir}/";
            return $cacheDir.md5($key);
        } else {
            $cacheDir .= $this->baseKey.'/';
            $filename = $this->baseKey;
            if ( $this->ftype ) {
                $cacheDir .= $this->ftype .'/';
                $filename .= '_'.$this->ftype;
            }
            if ( $this->factor ) {
                if ( is_numeric($this->factor) ) {
                    $cacheDir .= ($this->factor % self::$_FILE_OPACITY).'/';
                } else {
                    $factor = HashUtils::JSHash($this->factor);
                    $cacheDir .= ($factor % self::$_FILE_OPACITY).'/';
                }
                $filename .= '_'.$this->factor;
            }
            return $cacheDir.$filename.$extension;
        }

    }
1152781
public function add(array $file = null, $force = false)
    {
        $args   = array();
        if ($force) {
            $args[]  = '--force';
        }
        if ($file !== null) {
            $status = $this->getStatus();
            if (empty($status)) {
                return;
            }

            $files  = $this->resolveLocalGlobPath($file);
            foreach ($this->getStatus() as $status) {
                if (   $status['status'] != 'unversioned'
                    && in_array($status['file'], $files)
                ) {
                    array_splice($files, array_search($status['file'], $files), 1);
                }
            }

            if (empty($files)) {
                return;
            }

            $args[] = '--parents';
            $args[] = '--';
            $args   = array_merge($args, $files);
        } else {
            $toAdd      = array();
            $toRemove   = array();
            foreach ($this->getStatus() as $status) {
                if ($status['status'] == 'missing') {
                    $toRemove[] = $this->resolveLocalPath($status['file']);
                } else if ($status['status'] == 'unversioned') {
                    $toAdd[] = $this->resolveLocalPath($status['file']);
                }
            }

            if (!empty($toRemove)) {
                $this->remove($toRemove, false, $force);
            }
            if (empty($toAdd)) {
                return;
            }

            $args['--depth']    = 'infinity';
            $args[]             = '--';
            $args               = array_merge($args, $toAdd);
        }

        /** @var $result CallResult */
        $result = $this->getSvn()->{'add'}($this->getRepositoryPath(), $args);
        $result->assertSuccess(sprintf('Cannot add "%s" to "%s"',
            ($file !== null) ? implode(', ', $file) : '*', $this->getRepositoryPath()
        ));
    }
664648
public function sDiffStore($destination, $key, ...$keys) {
        return $this->send(array_merge(['sdiffstore', $destination], (array) $key, $keys));
    }
203100
public function getMergedBranches($ref = 'HEAD', $remote = false, $dir = null, $mustRun = false)
    {
        $args = ['branch', '--list', '--no-column', '--no-color', '--merged', $ref];
        if ($remote) {
            $args[] = '--remote';
        }
        $mergedBranches = $this->execute($args, $dir, $mustRun);
        $array = array_map(
            function ($element) {
                return trim($element, ' *');
            },
            explode("\n", $mergedBranches)
        );

        return $array;
    }
346549
private function traverseTreeForCompress(array &$tree, int $base,
        string $prefix = '') {

        // 先处理当前层级
        foreach ($tree as $code => $children_tree) {
            $state = $this->getState($base, $code);
            $this->check[$state] = $base;
        }

        // 再处理子级
        foreach ($tree as $code => $children_tree) {
            $state = $this->getState($base, $code);
            $word  = $prefix . $this->index_code[$code];

            // 计算此子级的check 即当前节点的base
            if ($children_tree) {
                $next_base = $this->findBegin($children_tree);
                $this->beginUse($next_base);
                $this->base[$state] = $next_base;

                $this->traverseTreeForCompress($children_tree, $next_base, $word);
            } else {
                // 叶节点
                $this->base[$state] = -$this->check[$state];

                // 创建 word 的 state 索引
                $this->word_states[$state] = $word;
            }
        }
    }
854624
public function getBatchInsertRequest($insertBindsByKeys) : StorageDataRequest
    {
        $self = $this;
        $request = new StorageDataRequest(
            [$insertBindsByKeys],
            function ($insertBindsByKeys) use ($self) {
                $results = [];
                foreach ($insertBindsByKeys as $id => $bind) {
                    $pointer = $self->getPointer($id, self::ADD_ACCESS);
                    if (!$pointer) {
                        $results[$id] = false;
                    }
                    
                    $res = fwrite($pointer, $this->_packData($bind));
                    $self->closePointer($pointer);

                    $results[$id] = $res ? true : false; 
                }
                
                return $results;
            }
        );

        return $request;
    }
63859
public static function copy($src, $dest, $force = false)
    {
        @set_time_limit((int) ini_get('max_execution_time'));

        // Eliminate trailing directory separators, if any
        $src = rtrim($src, '/\\');
        $dest = rtrim($dest, '/\\');

        if (!is_dir($src)) {
            throw new FilesystemException('Source folder not found', -1);
        }

        if (is_dir($dest) && !$force) {
            throw new FilesystemException('Destination folder exists', -1);
        }

        // Make sure the destination exists
        if (!static::create($dest)) {
            throw new FilesystemException('Cannot create destination folder', -1);
        }

        $sources = static::items($src, true, static::PATH_RELATIVE);

        // Walk through the directory copying files and recursing into folders.
        foreach ($sources as $file) {
            $srcFile = $src . '/' . $file;
            $destFile = $dest . '/' . $file;

            if (is_dir($srcFile)) {
                static::create($destFile);
            } elseif (is_file($srcFile)) {
                File::copy($srcFile, $destFile, $force);
            }
        }

        return true;
    }
6250
public function listContents($depth = 0, $filter = null, $type = 'all', $asHandlers = false)
	{
		$pattern = $this->path.'/*';

		if (is_array($filter))
		{
			$filters = $filter;
			$filter = new Filter;

			foreach ($filters as $f => $type)
			{
				if ( ! is_int($f))
				{
					$f = $type;
					$type = null;
				}

				$expected = true;

				if (strpos($f, '!') === 0)
				{
					$f = substr($f, 1);
					$expected = false;
				}

				$filter->addFilter($f, $expected, $type);
			}
		}

		if ($filter instanceof \Closure)
		{
			$callback = $filter;
			$filter = new Filter();
			$callback($filter);
		}

		if ( ! $filter)
		{
			$filter = new Filter;
		}

		$flags = GLOB_MARK;

		if ($type === 'file' and ! pathinfo($pattern, PATHINFO_EXTENSION))
		{
			// Add an extension wildcard
			$pattern .= '.*';
		}
		elseif ($type === 'dir')
		{
			$flags = GLOB_MARK | GLOB_ONLYDIR;
		}

		$contents = glob($pattern, $flags);

		// Filter the content.
		$contents = $filter->filter($contents);

		// Lower the depth for a recursive call
		if ($depth and $depth !== true)
		{
			$depth--;
		}

		$formatted = array();

		foreach ($contents as $item)
		{
			if ($filter->isCorrectType('dir', $item))
			{
				$_contents = array();

				if (($depth === true or $depth === 0) and ! $asHandlers)
				{
					$dir = new Directory($item);

					$_contents = $dir->listContents($item, $filter, $depth, $type);
				}

				if ($asHandlers)
				{
					$formatted[] = new Directory($item);
				}
				else
				{
					$formatted[$item] = $_contents;
				}
			}
			elseif ($filter->isCorrectType('file', $item))
			{
				if ($asHandlers)
				{
					$item = new File($item);
				}

				$formatted[] = $item;
			}
		}

		return $formatted;
	}
377375
private static function getCacheKey($ids, $buildDepth, $orderby=null, PagingInfo $pagingInfo=null) {
    $result = is_array($ids) ? join(',', $ids) : $ids;
    $result .= ','.$buildDepth;
    if ($orderby != null) {
      $result .= ','.(is_array($orderby) ? join(',', $orderby) : $orderby);
    }
    if ($pagingInfo != null) {
      $result .= ','.$pagingInfo->getOffset().','.$pagingInfo->getPageSize();
    }
    return md5($result);
  }
1266213
private static function _getValue($params, $keys, $keysCount, &$ancestorExist, $keyPrefix = '', &$cachedKeyValues = null)
    {
        $keyPath = $keyPrefix;
        $siblings = $params;
        $value = $params;

        if ($keysCount > 1) {
            // 查询缓存
            if ($cachedKeyValues !== null) {

                // todo 如果没有*号, 没必要重新合成路径
                $prefix = $keyPrefix;
                for ($i = 0; $i < $keysCount - 1; $i++) {
                    $key = $keys[$i];
                    if ($prefix === '')
                        $prefix = $key;
                    else if (is_integer($key) || $key === '*')
                        $prefix .= "[$key]";
                    else
                        $prefix .= ".$key";
                }

//                if (array_key_exists($prefix, $cachedKeyValues)) {
//                    echo "\n命中: key=$prefix" . ", value=" . $cachedKeyValues[$prefix] . "\n";
//                }
            }
        }

        for ($n = 0; $n < $keysCount; $n++) {
            $siblings = $value;
            $keyPrefix = $keyPath;

            $key = $keys[$n];
            if ($key === '*') {
                self::validateArr($siblings, null, $keyPrefix);
                $c = count($siblings);
                if ($c > 0) {
                    $subKeys = array_slice($keys, $n + 1);
                    $subKeysCount = $keysCount - $n - 1;

                    if ($subKeysCount) // *号后面还有keys
                    {
                        $values = [];
                        $ancestorExist = false;
                        for ($i = 0; $i < $c; $i++) {
                            $element = $siblings[$i];
                            $keyPath = $keyPrefix . "[$i]";
                            $aAncestorExist = false;
                            $aValue = self::_getValue($element, $subKeys, $subKeysCount, $aAncestorExist, $keyPath, $cachedKeyValues);
                            if ($aAncestorExist) {
                                $values[] = $aValue;
                                $ancestorExist = true;
                            }
//                            self::_validate($element, $subKeys, $subKeysCount, $validator, $keyPath, $ignoreRequired, $cachedKeyValues);
                        }
                    } else // *号是最后一级
                    {
                        $values = $siblings;

                        // todo 缓存数组本身的没什么用, 因为提取不到.
                        if ($cachedKeyValues !== null && $keyPrefix) {
                            $cachedKeyValues[$keyPrefix] = $siblings;
//                            echo "\n缓存: keyPrefix=$keyPrefix, key=$keyPath" . ", value=$siblings\n";
                        }
                    }
                    return $values;
                } else // 'items[*]' => 'Required' 要求items至少有1个元素, 但上面的循环不检测items==[]的情况
                    $value = null; // 这里是针对$value==[]这种情况的特殊处理
            } else {
                if (is_integer($key))
                    self::validateArr($siblings, null, $keyPrefix);
                else
                    self::validateObj($siblings, null, $keyPrefix);
                $value = @$siblings[$key];
            }

            if ($keyPrefix === '')
                $keyPath = $key;
            else if (is_integer($key) || $key === '*')
                $keyPath = $keyPrefix . "[$key]";
            else
                $keyPath = "$keyPrefix.$key";

            if ($value === null) {
                $n++;
                break;
            }
        }

        // 到这里$n表示当前的$value是第几层. 取值在[1, $keysCount]之间, 也就是说 $n 只可能小于或等于$keysCount
        if ($n == $keysCount) {
            $ancestorExist = true;
        } else {
            $ancestorExist = false;
            if ($cachedKeyValues !== null) {
                for (; $n < $keysCount; $n++) {
                    $keyPrefix = $keyPath;

                    $key = $keys[$n];

                    if ($keyPrefix === '')
                        $keyPath = $key;
                    else if (is_integer($key) || $key === '*')
                        $keyPath = $keyPrefix . "[$key]";
                    else
                        $keyPath = "$keyPrefix.$key";
                }
                $siblings = null;
            }
        }
        if ($cachedKeyValues !== null && $keyPrefix) {
            $cachedKeyValues[$keyPrefix] = $siblings; // 将父级数据缓存起来
//            echo "\n缓存: keyPrefix=$keyPrefix, key=$keyPath" . ", value=$siblings\n";
        }
        return $value;
    }
583450
public function getArchiveLink(string $archiveFormat = AbstractApi::ARCHIVE_TARBALL,
                                   string $ref = AbstractApi::BRANCH_MASTER): array
    {
        return $this->getApi()->request($this->getApi()->sprintf('/repos/:owner/:repo/:archive_format/:ref',
            $this->getRepositories()->getOwner(), $this->getRepositories()->getRepo(), $archiveFormat, $ref));
    }